Я клонировал ваш проект и смог проверить неудачный тест на своей машине.
Причина вашего провала теста в утверждении теста failingTestStoringNewObject
:
assertThat(countRowsInTable(jdbcTemplate, "sample_table")).isEqualTo(1);
заключается в том, что EntityManger
JPA (репозитории Spring Data JPA используют это под капотом) следует стратегии обратной записи и сохраняет изменения сущностей JPA в своем кэше первого уровня (в памяти). Сброс изменений в базе данных не всегда происходит, когда ваш код выполняет .save()
или любую другую операцию с базой данных с использованием EntityManager
.
EntityManger
пытается отложить очистку и, следовательно, синхронизировать свой кеш первого уровня с базой данных как можно позже. Об этом можно много прочитать, и я могу порекомендовать руководство Влада Михалчи по этому .
В вашем случае, когда вы аннотируете свой тест с помощью @Transactional
, ваши изменения будут отменены после теста и, следовательно, никогда не фиксируется в базе данных. Вы можете увидеть это в журнале теста:
2020-07-20 09:59:57.754 INFO 12648 --- [ Test worker] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext@2b8ade2d testClass = SimpleObjectResourceHttpTest, testInstance = pl.code.house.example.jdbc.template.jdbctemplatetest.SimpleObjectResourceHttpTest@
Для большей наглядности вы также можете включить SQL ведение журнала для ваших тестов с помощью
spring:
jpa:
show-sql: on
. видите, что на самом деле не выполняется инструкция INSERT
, а выполняется вызов для получения первичного ключа вашей сущности.
Если вы временно используете repository.saveAndFlush(newObj).toDto();
внутри SimpleObjectFacade
, вы Посмотрим, что это работает.
Я бы использовал SimpleObjectRepository
для вашего интеграционного теста и использовал его метод .count()
. В этом случае базовый EntityManager
распознает вызов той же таблицы и перед этим передаст sh свои текущие изменения, и вы получите ожидаемый результат. Потому что, если вы используете JdbcTemplate
, взаимодействие с EntityManager
отсутствует, и, следовательно, EntityManager
не грипп sh, он изменяется, когда вы go непосредственно в базу данных с SELECT COUNT(0) ...
.
ОБНОВЛЕНИЕ : если вы не хотите вносить какие-либо изменения и по-прежнему используете JdbcTemplate
в сочетании с Hibernate и JpaRepositories
, вы можете установить следующий грипп sh режим только для ваших тестов:
spring.jpa.properties.org.hibernate.flushMode=ALWAYS
Это гарантирует, что всегда грипп sh контекст постоянства