在使用@Transactional和@Commit时,java无法测试预期的异常
我使用的是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数据存储库,我想测试使用重复用户名时是否会出现异常。这个测试有效:
@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"));
}
}
但是,当用@Commit
添加@Transactional
时,该测试失败:
@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 ERROR 22790 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : Unique index or primary key violation: "UK_D8HGQ87BS4VPMC81NQ9G69G8X_INDEX_D ON PUBLIC.MYPROJECT_USER(USERNAME) VALUES ('wim', 1)"; SQL statement: insert into myproject_user (password, username, role, id) values (?, ?, 'ADMIN', ?) [23505-191] 2016-05-24 09:05:16.620 INFO 22790 --- [
main] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements 2016-05-24 09:05:16.629 WARN 22790 --- [ main] o.s.test.context.TestContextManager
: Caught exception while allowing TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener@589b3632] to process 'after' execution for test: method [public void com.spring.boot.test.user.UserRepositoryIntegrationTest.test()], instance [com.spring.boot.test.user.UserRepositoryIntegrationTest@3ca278bc], exception [java.lang.AssertionError: Expected exception: org.springframework.dao.DataIntegrityViolationException]
为什么测试失败?JUnit是否会在Spring提交事务之前检查是否引发了异常
# 1 楼答案
根据M.Deinum和Stephane Nicoll的评论,以下是工作版本:
请注意,需要调用这两个静态方法才能使其工作
# 2 楼答案
我需要在MVC控制器测试(
@WebAppConfiguration
)中测试DataIntegrityViolationException
,并通过@ControllerAdvice
在应用程序内部进行@ResponseStatus
修改。所以你的方法不适合我,太晚了。不幸的是@NotTransactional
注释在Spring 4中被排除在外,所以我只是将@Transactional
的测试与事务性测试分开。另见http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/testing.html#integration-testing-annotationsfrom更新。2种解决方案:
@Transactional(propagation = Propagation.NEVER)
# 3 楼答案
你不需要承诺。你只需要将你的工作单元刷新到数据库中,就可以看到
DataIntegrityViolationException
这在Spring Reference Manual中关于“假阳性”的说明中有描述。然而,请注意,
EntityManager
必须通过@PersistenceContext
(而不是@Autowired
)注射以下几点对你来说应该很好:
问候
Sam(Spring TestContext框架的作者)