我目前正在使用Spring开发REST Web服务,使用Hibernate作为ORM并使用黄瓜来编写验收测试。在cucumber-jvm测试中回滚事务
为了能够在场景之间回滚事务,我有以下代码,它在每个场景之前创建一个事务并在其之后进行回滚。
package com.orange.cainet.cucumber;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import cucumber.api.java.After;
import cucumber.api.java.Before;
@WebAppConfiguration
@ContextConfiguration("classpath:applicationContext.xml")
public class RollbackTransactionsBetweenScenarios {
@Autowired
PlatformTransactionManager transactionManager;
TransactionStatus transaction;
@Before
public void beforeScenario(){
transaction = transactionManager.getTransaction(new DefaultTransactionDefinition());
}
@After
public void afterScenario(){
transactionManager.rollback(transaction);
}
}
在步骤定义类,我用我的实体的自动装配Autowired CrudRepository创造什么样的是在给定的陈述和主张是什么在当时的声明。
我使用MockMvc模拟应用程序上下文并使用(post,get,...)发送假请求并将ResultActions保留为字段以在断言中使用它。
直到最近,这对我来说还是很好的,使用@Column(unique = true)来防止实体中某个字段的重复,并使用DataIntegrityViolationException来知道我是在什么时间以保存具有成对的场
try{
newUser = userRespoitory.save(newUser);
}
catch(DataIntegrityViolationException exception){
throw new UserNameAlreadyExistsException();
}
的问题是,DataIntegrityViolationException被抛出后,每当我在任何黄瓜步骤定义函数使用UserRepository.findOne(),测试引发错误
org.hibernate.AssertionFailure: null id in com.komalo.domain.User entry (don't flush the Session after an exception occurs)
我知道这是因为我在每个场景之前创建的事务,如果在使用UserRepository之前执行了此事务的回滚,它将正常工作。
所以我的问题是:
1)这是写测试,以正确的方式? ,因为我正在使用UserReposistory,这是我进行验收测试的一部分,但我认为它是由Spring Data实现的,因此它可以。
2)是否有办法继续使用事务,即使抛出异常之后?
3)这可以容易地通过不依赖于DataIntegrityViolationException和代替手动检查通过创建在像UserRepository.findOneByUsername(接口的额外方法),并用它来解决,但不是这一个额外的选择语句被执行??
我建议你,而不是回滚你的交易,你可以准备SQL脚本和清理数据库并重新填充每一个交互。这将确保您的数据在每次测试之前处于可信状态。 – Desorder 2014-10-07 03:13:12