Java 将@Transactional与@Commit一起使用时无法测试预期的异常
我使用的是Spring Boot 1.4.0.M3 我有一个Java 将@Transactional与@Commit一起使用时无法测试预期的异常,java,spring,junit,transactions,Java,Spring,Junit,Transactions,我使用的是Spring Boot 1.4.0.M3 我有一个@实体,它有一个用户名,应该是唯一的: @NotNull @Column(unique = true) @Pattern(regexp = "[a-zA-Z_\\-\\.0-9]+") @Size(min = 1, max = 30) private String username; 使用Spring数据存储库,我想测试使用重复用户名时是否会出现异常。该测试工作如下: @SpringBootTest @RunWith(SpringRu
@实体
,它有一个用户名
,应该是唯一的:
@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错误22790---[main]
o、 h.engine.jdbc.spi.SqlExceptionHelper:唯一索引或主键
违规行为:“UK_D8HGQ87BS4VPMC81NQ9G69G8X_索引打开”
PUBLIC.MYPROJECT_用户(用户名)值('wim',1');SQL语句:
在myproject_用户(密码、用户名、角色、id)中插入值(?,
[23505-191]2016-05-2409:05:16.620信息22790---[main]o.h.e.j.b.internal.AbstractBatchImpl:HH000010:发布时 它仍然包含JDBC语句2016-05-24 09:05:16.629 警告22790---[main]o.s.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提交事务之前检查是否抛出异常?根据M.Deinum和Stephane Nicoll的评论,这是工作版本:
@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
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"));
TestTransaction.flagForCommit();
TestTransaction.end();
}
}
请注意,两个静态方法都需要调用才能正常工作。您不需要提交。您只需将工作单元刷新到数据库中,即可查看
DataIntegrityViolationException
本手册中关于“误报”的说明对此进行了说明。但是,请注意,EntityManager
必须通过@PersistenceContext
注入(而不是@Autowired
)
以下内容对您来说应该很好:
@RunWith(SpringRunner.class)
@春靴测试
@交易的
公共类UserRepositoryIntegrationTest{
@自动连线
用户存储库;
@持久上下文
实体管理器实体管理器;
@测试(预期=DataIntegrityViolationException.class)
公开无效测试(){
save(User.createAdmin(repository.nextId(),“wim”,“123456”);
save(User.createAdmin(repository.nextId(),“wim”,“123456”);
entityManager.flush();
}
}
问候,
Sam(SpringTestContext框架的作者)我需要在MVC控制器测试(
@WebAppConfiguration
)中测试DataIntegrityViolationException
),并通过@ControllerAdvice
在应用程序内部进行@ResponseStatus
修改。所以你的方法不适合我,太晚了。不幸的是,@NotTransactional
注释在Spring4中被排除在外,所以我只是将@Transactional
和NotTransactional的测试分开。另见
@不推荐使用NotTransactional
更新。2种解决方案:
- 明确区分事务性测试和非事务性测试
- 在不需要事务的地方使用
@Transactional(propagation=propagation.NEVER)
TestTransaction#end
。感谢您指向该类。我不知道它的存在。我已经添加了一个完整工作版本的答案。这不是问题的答案。你可以在回答中加上这句话作为评论,或者就这个问题单独提问。是的,我同意你的看法。但这对和你有同样问题的人来说是个不错的选择。很好,你让我度过了美好的一天,这是一个完美的答案,简短而甜蜜