У Вас есть несколько проблем здесь.
Во-первых , различные версии Oracle, которую Вы используете, являются причиной ошибки статистики таблицы - у меня была та же проблема, когда некоторые наши Базы данных 10 г Oracle были обновлены до Выпуска 2, и некоторые были все еще на Выпуске 1, и я подкачивал.DMP файлы между ними.
решение, которое работало на меня, состояло в том, чтобы использовать ту же версию exp
и imp
инструменты, чтобы сделать экспорт и импорт на различных экземплярах Базы данных. Это было самым легким сделать при помощи того же ПК (или Oracle Server) для издания всего экспорта и импорта команд.
, Во-вторых , я подозреваю, что Вы добираетесь ORA-00959: tablespace 'A_TBLSPACE' does not exist
, потому что Вы пытаетесь импортировать.DMP файл из полноценной Базы данных Oracle в 10 г Express Edition (XE) База данных, которая, по умолчанию, создает единственную, предопределенную табличную область, названную USERS
для Вас.
, Если это так, тогда необходимо будет сделать следующее..
С Вашим.DMP файлом, создайте файл SQL, содержащий структуру (Таблицы):
imp <xe_username>/<password>@XE file=<filename.dmp> indexfile=index.sql full=y
Открывают индексный файл (index.sql) в текстовом редакторе, который может сделать, находят и заменяют по всему файлу и выходят, следующее находят и заменяют операторы IN ORDER (проигнорируйте одинарные кавычки..'):
Find: 'REM<space>' Replace: <nothing>
Find: '"<source_tablespace>"' Replace: '"USERS"'
Find: '...' Replace: 'REM ...'
Find: 'CONNECT' Replace: 'REM CONNECT'
Сохраняют индексный файл, затем работают, он против Вашей Oracle Express Edition считает (я нахожу, лучше создавать новую, пустую учетную запись пользователя XE - или отбрасывать и воссоздавать, если я обновляюсь):
sqlplus <xe_username>/<password>@XE @index.sql
Наконец выполняет тот же.DMP файл, с которым Вы создали индексный файл против той же учетной записи для импорта данных, хранимых процедур, представления и т.д.:
imp <xe_username>/<password>@XE file=<filename.dmp> fromuser=<original_username> touser=<xe_username> ignore=y
можно получить страницы ошибок Oracle при попытке создать определенные объекты, такие как Задания Базы данных, поскольку Oracle попытается использовать тот же Идентификатор Базы данных, который, скорее всего, перестанет работать, как Вы находитесь на различной Базе данных.
Просто создание поддельного перечисления значений не будет достаточно, в конечном счете также необходимо управлять целочисленным массивом, который создается компилятором.
<час> На самом деле для создания поддельного перечисления значений Вам даже не нужна никакая платформа насмешки. Можно просто использовать Objenesis для создания нового экземпляра класса Enum (да, это работает), и затем используйте простое отражение Java для установки частных полей name
и ordinal
, и у Вас уже есть свой новый перечислимый экземпляр.
Используя платформу Spock для тестирования, это посмотрело бы что-то как:
given:
def getPrivateFinalFieldForSetting = { clazz, fieldName ->
def result = clazz.getDeclaredField(fieldName)
result.accessible = true
def modifiers = Field.getDeclaredFields0(false).find { it.name == 'modifiers' }
modifiers.accessible = true
modifiers.setInt(result, result.modifiers & ~FINAL)
result
}
and:
def originalEnumValues = MyEnum.values()
MyEnum NON_EXISTENT = ObjenesisHelper.newInstance(MyEnumy)
getPrivateFinalFieldForSetting.curry(Enum).with {
it('name').set(NON_EXISTENT, "NON_EXISTENT")
it('ordinal').setInt(NON_EXISTENT, originalEnumValues.size())
}
<час> , Если Вы также хотите MyEnum.values()
метод возвратить новое перечисление, теперь можно или использовать JMockit для насмешки эти values()
вызов как [1 152]
new MockUp<MyEnum>() {
@Mock
MyEnum[] values() {
[*originalEnumValues, NON_EXISTENT] as MyEnum[]
}
}
, или можно снова использовать простое отражение для управления $VALUES
поле как:
given:
getPrivateFinalFieldForSetting.curry(MyEnum).with {
it('$VALUES').set(null, [*originalEnumValues, NON_EXISTENT] as MyEnum[])
}
expect:
true // your test here
cleanup:
getPrivateFinalFieldForSetting.curry(MyEnum).with {
it('$VALUES').set(null, originalEnumValues)
}
<час> , пока Вы не имеете дело с switch
выражение, но приблизительно с [1 111] с или подобный, или просто первая часть или первая и вторая часть могли бы быть достаточно для Вас.
, Если Вы однако имеете дело с switch
выражение, например, желаете 100%-е покрытие для default
случай, который выдает исключение в случае, если перечисление расширяется как в Вашем примере, вещи становятся немного более сложными и в то же время немного более легкий.
немного более сложный, потому что необходимо сделать некоторое серьезное отражение для управления синтетическим полем, которое компилятор генерирует в синтетическом анонимном внутреннем классе, который генерирует компилятор, таким образом, не действительно очевидно, что Вы делаете и Вы связываетесь с фактической реализацией компилятора, таким образом, это могло повредиться в любое время в любой версии Java или даже если Вы используете различные компиляторы для той же версии Java. Это на самом деле уже отличается между Java 6 и Java 8.
немного более легкий, потому что можно забыть первые две части этого ответа, потому что Вы не должны создавать новый перечислимый экземпляр вообще, просто необходимо управлять int[]
, которым необходимо управлять так или иначе для создания теста, который Вы хотите.
я недавно нашел очень хорошую статью относительно этого в [1 138] https://www.javaspecialists.eu/archive/Issue161.html .
большая часть информации там все еще допустима, за исключением того, что теперь внутренний класс, содержащий карту переключателя, больше не является именованным внутренним классом, а анонимным классом, таким образом, Вы не можете использовать getDeclaredClasses
больше, но должны использовать другой подход, показанный ниже.
В основном полученный в итоге, включите уровень байт-кода, не работает с перечислениями, но только с целыми числами. Таким образом, то, что делает компилятор, он создает анонимный внутренний класс (ранее именованный внутренний класс согласно записи статьи, это - Java 6 по сравнению с Java 8), который содержит один статический финал int[]
поле, названное $SwitchMap$net$kautler$MyEnum
, который заполнен целыми числами 1, 2, 3... в индексах [1 118] значения.
Это означает, когда код прибывает в фактический переключатель, он делает
switch(<anonymous class here>.$SwitchMap$net$kautler$MyEnum[myEnumVariable.ordinal()]) {
case 1: break;
case 2: break;
default: throw new AssertionError("Missing switch case for: " + myEnumVariable);
}
, Если бы теперь myEnumVariable
имел бы значение NON_EXISTENT
созданным в первом шаге выше, Вы или добрались бы ArrayIndexOutOfBoundsException
, если Вы установите ordinal
на некоторое значение, больше, чем массив компилятор, сгенерированный, или Вы получили бы одно из других значений случая переключателя в противном случае в обоих случаях, то это не поможет протестировать требуемый default
случай.
Вы могли теперь получить этот int[]
поле и согласовать его для содержания отображения для orinal Вашего NON_EXISTENT
перечислимый экземпляр. Но поскольку я сказал ранее, для точно этого примера использования, тестируя default
случай, Вам не нужны первые два шага вообще. Вместо этого Вы можете простой приводить любой из существующих перечислимых примеров к коду под тестом и просто управлять отображением int[]
, так, чтобы default
случай был инициирован.
, Таким образом, все, что необходимо для этого тестового сценария, является на самом деле этим, снова записанным в Spock (Groovy) код, но можно легко адаптировать его к Java также:
given:
def getPrivateFinalFieldForSetting = { clazz, fieldName ->
def result = clazz.getDeclaredField(fieldName)
result.accessible = true
def modifiers = Field.getDeclaredFields0(false).find { it.name == 'modifiers' }
modifiers.accessible = true
modifiers.setInt(result, result.modifiers & ~FINAL)
result
}
and:
def switchMapField
def originalSwitchMap
def namePrefix = ClassThatContainsTheSwitchExpression.name
def classLoader = ClassThatContainsTheSwitchExpression.classLoader
for (int i = 1; ; i++) {
def clazz = classLoader.loadClass("$namePrefix\$i")
try {
switchMapField = getPrivateFinalFieldForSetting(clazz, '$SwitchMap$net$kautler$MyEnum')
if (switchMapField) {
originalSwitchMap = switchMapField.get(null)
def switchMap = new int[originalSwitchMap.size()]
Arrays.fill(switchMap, Integer.MAX_VALUE)
switchMapField.set(null, switchMap)
break
}
} catch (NoSuchFieldException ignore) {
// try next class
}
}
when:
testee.triggerSwitchExpression()
then:
AssertionError ae = thrown()
ae.message == "Unhandled switch case for enum value 'MY_ENUM_VALUE'"
cleanup:
switchMapField.set(null, originalSwitchMap)
В этом случае Вам не нужна никакая платформа насмешки вообще. На самом деле это не помогло бы Вам так или иначе, поскольку никакая платформа насмешки, о которой я знаю, не позволяет Вам дразнить доступ к массиву. Вы могли использовать JMockit или любую платформу насмешки для насмешки возвращаемого значения [1 129], но это снова просто приведет к другому ответвлению переключателя или AIOOBE.
то, Что этот код я просто показанный делаю:
ClassNotFoundException
брошен [1 131], тестовые сбои, который предназначается, потому что это означает компиляцию кода с компилятором, который следует другой стратегии или шаблону именования, таким образом, необходимо добавить еще некоторую аналитику для покрытия различных стратегий компилятора включения перечислимых значений. Поскольку, если класс с полем найден, break
листы, для цикла и тест могут продолжиться. Эта целая стратегия, конечно, зависит от анонимных классов, пронумерованных, начиная от 1 и без разрывов, но я надеюсь, что это - довольно безопасное предположение. Если Вы имеете дело с компилятором, где дело обстоит не так, ищущий алгоритм должен быть адаптирован соответственно. default
случай, пока у Вас нет перечисления с 2 147 483 647 значениями finally
блок, если Вы не используете Spock, в cleanup
блок при использовании Spock) для проверки, это не влияет на другие тесты на том же классе, исходная карта переключателя отложена в поле