单元测试基类默认为回滚
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/ApplicationContextTest.xml" })
@Transactional
@TransactionConfiguration(defaultRollback = true)
public abstract class AbstractTest {}
FooService中存在一个标注了事务注解的方法
class FooService{
@Transaction
public void doSomething(...){
//...
insertFoo(foo);
if(!meetSomeCondition){ //不满足某一条件 抛异常
throw new RuntimeException("XXX");
}
//...
}
}
现有一个FooServiceTest
public class FooServiceTest extends AbstractTest{
@Autowired
private FooService service;
@Test
public void test_doSomething_failed_because_not_meet_some_condition(){
try{
service.doSomething(...);
fail();
}catch(Exception e){
equals("XXX",e.getMessage())
}
//校验抛出异常后 是否回滚了
int count = service.getFooCount(...);
assert(0,count); //为0 表示回滚了
}
}
但执行此单元测试 失败
java.lang.AssertionError: expected:<0> but was:<1>
似乎是因为整个单元测试期间使用了同一个事务, 只有在所有测试方法都结束后才会回滚。
有没有好的办法处理这种情况呢? 如能使基类全局的@Transactional
对某个测试方法不生效 , 这时犹如正常调用该方法使用的就是目的方法自带的事务了。
尝试了下面的方法 都未成功
尝试一:
@Test
@Rollback(false)
public void test_doSomething_failed_because_not_meet_some_condition(){...}
尝试二:
专门创建一个测试类 仅包含该测试回滚方法
//显式指定不回滚
@TransactionConfiguration(defaultRollback = false)
public class FooServiceRollbackTest extends AbstractTest{
@Test
public void test_doSomething_failed_because_not_meet_some_condition(){...}
}
上面两种尝试结果一样
仍是测试失败
java.lang.AssertionError: expected:<0> but was:<1>
同时控制台中还多了异常
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:720)
原因是测试方法(
test_doSomething_failed_because_not_meet_some_condition
)里调用的service方法(service.doSomething
)中的@Transactional
会复用外部测试方法的事务, 所以直到测试方法结束后才会回滚, 所以在测试方法内部校验回滚肯定失败。解决方法
使用
Propagation.NOT_SUPPORTED
会取消外部事务, 这时只会使用servcie方法自己的事务。缺点:
测试方法里的数据库操作 如添加一些测试数据 不会回滚 于是会污染数据库