Невозможно сгенерировать исключение нарушения ограничения при тестировании ограничений Hibernate @Check

Я играю с аннотацией Hibernate @Check, но мой тест не может быть провален, если ограничения не выполнены. В настоящее время просто используется конфигурация загрузки Spring по умолчанию с базой данных H2.

Что мне не хватает? Должен ли быть какой-то промывать после save(..)?

При запуске теста я вижу, что таблица создана правильно. Если я скопирую строку создания из журнала и использую ее для создания таблицы в моей «реальной» базе данных Postgres, я могу протестировать различные вставки и увидеть, что с этой строкой все в порядке с ограничениями.

Сущность

@Getter @Setter
@Entity @Check(constraints = "a IS NOT NULL OR b IS NOT NULL")
public class Constrained {

    @Id @GeneratedValue
    private Long id;

    private String a, b;
}

Тестовое задание

@DataJpaTest
@RunWith(SpringRunner.class)
public class HibernateCheckTest {

    @Resource // this repo is just some boiler plate code but attached at 
              // the bottom of question
    private ConstrainedRepository repo;

    @Test @Transactional // also tried without @Transactional
    public void test() {
        Constrained c = new Constrained();
        repo.save(c); // Am I wrong to expect some constraint exception here?
    }
}

Скрипт генерации таблицы при запуске теста

create table constrained (id bigint not null, a varchar(255), b varchar(255), primary key (id), check (a IS NOT NULL OR b IS NOT NULL))

Репозиторий (в репо особо не видно, а просто показать):

public interface ConstrainedRepository
            extends CrudRepository<Constrained, Long> {
}

ТЕМ НЕ МЕНИЕ

Если я использую EntityManager, добавляю в свой тестовый класс:

@PersistenceContext
private EntityManager em;

и делать то же самое:

em.persist(c);
em.flush();

вместо repo.save(c) я получу исключение.

А ТАКЖЕ

более внимательное изучение журнала оригинального теста с repo.save(c) показывает:

org.springframework.test.context.transaction.TransactionContext:139 - Rolled back transaction for test:
...
testException = [null],

поэтому по какой-то причине эта ошибка просто переносится и регистрируется. Как его "развернуть" и выбросить при использовании репозитория для сохранения?

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

Ответы 2

В ConstrainedRepository расширите JpaRepository вместо CrudRepository, затем используйте:

repo.saveAndFlush(c);

вместо того:

repo.save(c);

Проверка выполняется в базе данных, и это происходит только тогда, когда изменения (в данном случае оператор INSERT) сбрасываются в базу данных.

Без явного сброса Hibernate отложит отправляет операторы в базу данных до тех пор, пока транзакция не будет зафиксирована или пока не будет выполнен запрос.

Однако из документации Spring DataJpaTest:

By default, data JPA tests are transactional and roll back at the end of each test.

Итак, в этом случае фиксации нет. Транзакция откатывается, и операторы никогда не сбрасываются в базу данных, поэтому исключение никогда не генерируется.

Спасибо. Я бы предположил что-то подобное. Я видел этот метод в некоторых вопросах и ответах, но теперь моя проблема в том, что мои репозитории не содержат этого метода? Сконструировать myt-репо или протестировать как-то иначе? (я тоже просматриваю документы, но если вы знаете быстрый ответ)

pirho 10.11.2018 11:54

Ах, извините, этот метод находится в JpaRepository, но не в CrudRepository. Обновили мой ответ.

codemonkey 10.11.2018 12:15
Ответ принят как подходящий

Благодаря отвечать от Codemonkey я смог найти решение. Это разрешается добавлением:

@org.springframework.transaction.annotation.Transactional(propagation = 
                                                     Propagation.NOT_SUPPORTED)

в мой тестовый класс.

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