【发布时间】:2016-09-21 06:17:29
【问题描述】:
我正在使用 Spring Boot 1.4.0.M3。
我有一个 @Entity 有一个 username 应该是唯一的:
@NotNull
@Column(unique = true)
@Pattern(regexp = "[a-zA-Z_\\-\\.0-9]+")
@Size(min = 1, max = 30)
private String username;
使用 Spring Data Repository,我想测试使用重复用户名时是否会出现异常。此测试有效:
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserRepositoryIntegrationTest {
@Autowired
private UserRepository repository;
@Test(expected = DataIntegrityViolationException.class)
public void test() {
repository.save(User.createAdmin(repository.nextId(), "wim", "123456"));
repository.save(User.createAdmin(repository.nextId(), "wim", "123456"));
}
}
但是,将@Transactional 与@Commit 添加时,此测试失败:
@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
public class UserRepositoryIntegrationTest {
@Autowired
private UserRepository repository;
@Test(expected = DataIntegrityViolationException.class)
@Commit
public void test() {
repository.save(User.createAdmin(repository.nextId(), "wim", "123456"));
repository.save(User.createAdmin(repository.nextId(), "wim", "123456"));
}
}
但是查看日志记录,DataIntegrityViolationException 被抛出:
2016-05-24 09:05:16.619 错误 22790 --- [主要] o.h.engine.jdbc.spi.SqlExceptionHelper :唯一索引或主键 违规:“UK_D8HGQ87BS4VPMC81NQ9G69G8X_INDEX_D ON PUBLIC.MYPROJECT_USER(USERNAME) VALUES ('wim', 1)"; SQL 语句: 插入 myproject_user(密码、用户名、角色、id)值(?, ?, '管理员', ?) [23505-191] 2016-05-24 09:05:16.620 信息 22790 --- [
主要] o.h.e.j.b.internal.AbstractBatchImpl:HHH000010:发布时 它仍然包含 JDBC 语句 2016-05-24 09:05:16.629 WARN 22790 --- [主] os.test.context.TestContextManager
: 在允许 TestExecutionListener 时捕获异常 [org.springframework.test.context.transaction.TransactionalTestExecutionListener@589b3632] 处理“后”执行测试:方法 [public void com.spring.boot.test.user.UserRepositoryIntegrationTest.test()], 实例 [com.spring.boot.test.user.UserRepositoryIntegrationTest@3ca278bc], 异常 [java.lang.AssertionError:预期异常: org.springframework.dao.DataIntegrityViolationException]
为什么测试失败?会不会是 JUnit 在 Spring 提交事务之前检查是否抛出异常?
【问题讨论】:
-
正如预期的那样......该异常将在事务提交之后发生。事务在方法结束后提交。所以基本上在检查的那一刻没有例外。你用这个改变了测试的行为。你需要在你的方法中提交。
-
“在允许 TestExecutionListener 时捕获异常”说明了一切。你想提交,但你想断言提交失败。 JUnit 和 Spring 彼此不了解,因此您不能对这些东西使用 JUnit 断言。正如马丁所说,在你的测试中使用
TestTransaction#end。 -
感谢您指向该课程。不知道它的存在。我已经添加了完整工作版本的答案。
标签: java spring junit transactions