Как переопределить insertable = false для модульного теста

Я в некотором роде гость в другой системе в нашем приложении, и я не хочу вносить какие-либо изменения с крупномасштабными разветвлениями.

Я пишу юнит-тест с нуля, так как предыдущий автор не заморачивался. (Ворчание.) Я пытаюсь вставить строку, чтобы проверить свой запрос с помощью JPA / hibernate, и был удивлен, увидев следующую ошибку:

javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: integrity constraint violation: NOT NULL check constraint; SYS_CT_14316 table: OPTIONVALUE column: OPTION_INDEX

    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1306)
    at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:989)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:293)
    at com.sun.proxy.$Proxy109.flush(Unknown Source)

Особенно, когда я знал, что установил значение, потому что мне нужно было написать для него сеттер. Затем на одном из объектов я нашел следующее определение (которое мне пришлось искать):

public static final String OPTION_VALUE_POSITION_COLUMN = "option_index";
@Column(name = OPTION_VALUE_POSITION_COLUMN, insertable = false, updatable = false, nullable = false)
private int position;

Это объясняет, почему я все еще получаю ноль в этом столбце.

У меня нет ОГРОМНОЙ проблемы с удалением вставляемого элемента, потому что он не создается автоматически, так почему бы вам НЕ включать его, если вы вставляете запись, что, очевидно, никогда не происходит внутри системы. А обновляемый защитит его. Но я действительно не хочу, если мне не нужно.

Итак, мой вопрос: есть ли способ переопределить это только для модульного теста. Я пробовал погуглить пару вещей, но сформулировать это было немного проблематично, и я ничего не нашел.

Значит, вы пишете интеграционный тест, а не модульный тест?

daniu 31.07.2018 15:42

@daniu С точки зрения. Как проверить запрос без механизма запросов и данных?

Thom 31.07.2018 15:45

Вы этого не сделаете, использовать двигатель - это нормально. Однако, как только вы начинаете манипулировать тестируемым кодом, эти тесты становятся гораздо менее значимыми.

daniu 31.07.2018 15:48

@daniu Вы не ошиблись, но какие у меня варианты?

Thom 31.07.2018 15:51

Вы имеете в виду, как использовать orm.xml?

user3973283 31.07.2018 16:13

@BillyFrost Каким образом?

Thom 31.07.2018 16:23

поскольку orm.xml переопределяет то, что определено в аннотациях ...

user3973283 31.07.2018 16:25

и вы говорите, что я могу использовать это, например, в тестовых ресурсах или в чем-то подобном?

Thom 31.07.2018 16:26
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
8
350
2

Ответы 2

Обычно вы можете переопределить любой класс в тестовых пакетах, и он будет загружен вместо основного класса, потому что он имеет более высокий приоритет. Пути загрузки классов обычно имеют приоритет в следующем порядке:

  1. Тестовые классы (если запущен тест)
  2. Ресурсы для тестирования (если запущен тест)
  3. Основные классы
  4. Основные ресурсы
  5. Банки тестовых зависимостей (если запущен тест)
  6. Основные jar-файлы зависимостей

Вы можете проверить это так:

// I have yet to run into a custom ClassLoader that does not extend URLClassLoader
URLClassLoader urls = (URLClassLoader) getClass().getClassLoader();
for (URL url : urls.getURLs()) {
    System.out.println(url);
}

Однако здесь есть небольшая проблема. ClassLoader Hibernate может (а может и не прочитать) переопределенный класс из Test, если у вас нет файла конфигурации persistence.xml, orm.xml или чего-то еще в тестовых ресурсах. Это может быть, а может и не быть, но если вам нужно иметь отдельную конфигурацию в тесте, тогда должен перечисляет все классы, которые необходимо просканировать. Вы не можете полагаться на запись <exclude-unlisted-classes>false</exclude-unlisted-classes>, потому что сканер Hibernate знает глубину и не проникает в иерархию пути к классу глубже, чем уровень, на котором он нашел конфигурационный XML.

Я не знаю, лучшее ли это решение, но в некоторых случаях это может быть законный обходной путь.

Я использовал необработанные запросы для вставки / обновления своих объектов в следующих случаях:

Query query = entityManager.createNativeQuery("insert into MY_TABLE " + 
            "(ID, NAME) values (1, 'user1')");
query.executeUpdate();

Другие вопросы по теме