在集成测试中每个方法不回滚后 Spring Data JPA 数据库更改
Posted
技术标签:
【中文标题】在集成测试中每个方法不回滚后 Spring Data JPA 数据库更改【英文标题】:Spring Data JPA database changes after each method don't roll back in integration tests 【发布时间】:2020-08-08 19:01:26 【问题描述】:我正在使用 JUnit 5 和 Spring boot 2.2.4 来集成测试我的 Spring Boot 应用程序代码与 MySQL 5.7 数据库,但 strong>以前的测试方法对数据库所做的更改不会回滚,这会导致后面的错误。
我尝试了来自不同 *** 帖子的答案,例如添加 @Transactional
(来自 Spring)、@Rollback
(方法和类级别)、@TestExecutionListeners(listeners = TransactionalTestExecutionListener.class)
。我已经单独(以及组合)测试了这些选项,但将它们一起添加到测试代码中。
这是我的测试代码:
@DataJpaTest
@Transactional
@Rollback
@ExtendWith(SpringExtension.class)
@Import(UserUsecasesImpl.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserUsecasesImplINTTest
@Autowired
private TestEntityManager entityManager;
@Autowired
@Spy
private UserRepository userRepository;
@Autowired
private UserUsecases userUsecases;
@Test
void injectedComponentsAreNotNull()
assertNotNull(entityManager);
assertNotNull(userRepository);
assertNotNull(userUsecases);
@Test
@Rollback
void Create_EntityAlreadyExists_ReturnsException()
// set up
User expected = UserFixture.user1.toBuilder().build();
// entityManager.persistAndFlush(expected);
userRepository.saveAndFlush(expected);
// execute
User actual = userUsecases.create(expected);
// verify
assertEquals(expected, actual);
verify(userRepository).findOne(any(Example.class));
verify(userRepository, never()).save(any(User.class));
verifyNoMoreInteractions();
@Test
void Find_WhenUserPresent_ReturnUser()
// // set up
User expected = UserFixture.user1.toBuilder().build();
entityManager.persistAndFlush(expected);
// execute
User actual = userRepository.find(expected);
// verify
assertEquals(expected, actual);
@Test
// @Transactional
void Find_WhenUserNotPresent_ReturnNull()
// // set up
User expected = UserFixture.user1.toBuilder().build();
// entityManager.persistAndFlush(UserFixture.user2.toBuilder().build());
// execute
User actual = userUsecases.find(expected);
// verify
assertNull(actual);
UserUsecasesImpl
是我要测试的类,其中包含创建用户、查找用户、获取所有用户等用例。代码中的其他任何地方都没有特殊配置。
【问题讨论】:
好的,请把所有类重命名为正常的命名约定,我看不懂。让Repository调用类实现JPA存储库,不要调用POJO'DAO'和Datasource??我读到这里就得强迫症了。 好的。给您带来的不便,我们深表歉意。 @JAsgarov 提到的类名没有意义。请将此更改为正确的命名,否则将无法阅读。第二件事,为什么要对您的实际数据库进行集成测试。在类路径中使用 h2,范围为测试或 testRuntimeOnly。在您的资源中定义适当的 application-test.yml。声明测试属性源并使用它。我看到许多注释没有用,因为 DataJpaTest 本身就是您使用的大多数注释的元注释。 我已经更新了类名。 @Priyak Dey 最初我使用的是 h2,但我想确保数据库中发生了什么,我能想到的最简单的方法是使用 mysql,以便我可以连接到它并查看断点处发生的情况。我定义了一个由 spring.profiles.active="test" 激活的附加 application-test.properties。 这不是一个解决方案,但我能够让测试用例为我工作。我从 MySQL 切换到 H2,然后在每个测试方法之后回滚。 【参考方案1】:请实施以下修复,如果问题仍然存在,请告诉我:
-
删除所有
@Transactional
和@Rollback
。保留@DataJpaTest
,默认情况下,这会使您的所有测试@Transactional,因此默认情况下会将它们全部回滚。
不要使用saveAndFlush
。刷新部分是将保存操作刷新到数据库中,很可能会导致您的问题。请改用save
。更多在这里https://www.baeldung.com/spring-data-jpa-save-saveandflush
如果您期望出现异常,请使用 assertThrows
断言它。
一般来说,尽量不要同时将你知道的每一个注释都扔到混合中。根据需要一次添加一个,尝试了解它们的作用。
什么是 UserUseCases,为什么它会执行我希望 Repository 类执行的大部分逻辑?
【讨论】:
我尝试了您推荐的建议,尤其是第二条但没有解决问题(刷新并不意味着提交***.com/questions/14581865/hibernate-flush-and-commit)。 Spring Data(或休眠)是否不依赖于数据库的本机事务,如果是这种情况,即使它已将数据推送到数据库,它也应该能够回滚。我实际上是从 Flutter 搬到 Spring 的,在那里我会遵循这个结构 resocoder.com/2019/08/27/…。 TL;DR 用例可能与超过 1 个存储库交互。以上是关于在集成测试中每个方法不回滚后 Spring Data JPA 数据库更改的主要内容,如果未能解决你的问题,请参考以下文章