spring單元測試異常回滾的簡單總結

Spring 單元測試回滾總結java

目的方法spring

@Transactional
    public void insertFooAndThrowException(){
        // 先插入 而後拋出異常
        mapper.insertFoo(RandomStringUtils.randomAlphanumeric(20)); 
        throw new RuntimeException("Mock throw exception after insert foo");
    }

測試類sql

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/ApplicationContextTest.xml" })
public class TransactionRollbackTest{
    @Autowired
    private FooService fooService;
    @Test
    public void test_insertFooAndThrowException(){
        fooService.insertFooAndThrowException();
    }
}

一、 目的方法不含事務註解(//@Transactional) 執行過程當中拋出異常 此時會插入成功session

對應sql爲:app

2016-06-18T09:26:47.905229Z   33 Query    SET autocommit=1
2016-06-18T09:26:47.939430Z   33 Query    select @@session.tx_read_only
2016-06-18T09:26:47.939875Z   33 Query    insert into foo(a) values('OXrJKEkGCnnyH010ZkTv')

二、 目的方法含事務註解 若執行過程當中拋了異常 會自動回滾dom

2016-06-18T09:19:05.766030Z   31 Query    SET autocommit=0
2016-06-18T09:19:05.829996Z   31 Query    select @@session.tx_read_only
2016-06-18T09:19:05.830454Z   31 Query    insert into foo(a) values('oH2AgMnkrScpf4fGccIo')
2016-06-18T09:19:05.831384Z   31 Query    rollback

三、 目的方法含事務註解 但測試類顯式指定不回滾 以下所示單元測試

@TransactionConfiguration(defaultRollback = false)
public class TransactionRollbackTest

此時實際仍會回滾測試

2016-06-18T09:29:51.509882Z   35 Query    SET autocommit=0
2016-06-18T09:29:51.575956Z   35 Query    select @@session.tx_read_only
2016-06-18T09:29:51.576327Z   35 Query    insert into foo(a) values('RN2pujPfOA03MbxIkgjI')
2016-06-18T09:29:51.577155Z   35 Query    rollback

此種情形 與2相似lua

四、 目的方法含事務註解 測試類也有事務註解且顯式指定不回滾 以下所示spa

@Transactional
@TransactionConfiguration(defaultRollback = false)
public class TransactionRollbackTest

執行測試 會有以下的異常

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)
    at org.springframework.test.context.transaction.TransactionalTestExecutionListener$TransactionContext.endTransaction(TransactionalTestExecutionListener.java:597)

但實際仍會回滾

2016-06-18T09:32:42.072941Z   37 Query    SET autocommit=0
2016-06-18T09:32:42.134612Z   37 Query    select @@session.tx_read_only
2016-06-18T09:32:42.135024Z   37 Query    insert into foo(a) values('SeLtrEiQdkTRmcnjNNAy')
2016-06-18T09:32:42.136505Z   37 Query    rollback

爲何在測試類中添加了事務註解就會報上述異常呢? 事務註解放在測試類與目的方法中的區別是?

下面代碼處加上斷點 比較調用鏈

doRollback:284, DataSourceTransactionManager (org.springframework.jdbc.datasource)
  • 僅在目的方法中有事務註解 測試類無事務註解

at org.springframework.jdbc.datasource.DataSourceTransactionManager.doRollback(DataSourceTransactionManager.java:284)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:849)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:826)
at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:496)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
at com.foo.service.FooService$$EnhancerBySpringCGLIB$$58f57234.insertFooAndThrowException(<generated>:-1)
at com.foo.service.TransactionRollbackTest.test_insertFooAndThrowException(TransactionRollbackTest.java:26)
  • 目的方法與測試類均有事務註解

at org.springframework.jdbc.datasource.DataSourceTransactionManager.doRollback(DataSourceTransactionManager.java:284)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:849)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:716)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener$TransactionContext.endTransaction(TransactionalTestExecutionListener.java:597)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.endTransaction(TransactionalTestExecutionListener.java:296)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.afterTestMethod(TransactionalTestExecutionListener.java:189)
at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:416)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:91)

五、目的方法含事務註解 測試類含事務註解且設置默認回滾

@Transactional
@TransactionConfiguration(defaultRollback = true)
public class TransactionRollbackTest

沒有上述異常 且多了以下的日誌輸出

016-06-18 17:55:15,644 - org.springframework.test.context.transaction.TransactionalTestExecutionListener -2126 [main] INFO   - Rolled back transaction after test execution for test context [DefaultTestContext@3310ce7b testClass = TransactionRollbackTest, testInstance = com.foo.service.TransactionRollbackTest@1464076e, testMethod = test_insertFooAndThrowException@TransactionRollbackTest, testException = java.lang.RuntimeException: Mock throw exception after insert foo, mergedContextConfiguration = [MergedContextConfiguration@3323d137 testClass = TransactionRollbackTest, locations = '{classpath:spring/ApplicationContextTest.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]

sql爲

2016-06-18T09:55:15.578650Z   41 Query    SET autocommit=0
2016-06-18T09:55:15.641818Z   41 Query    select @@session.tx_read_only
2016-06-18T09:55:15.642228Z   41 Query    insert into foo(a) values('1HlH0xmi5bJL01GlEucm')
2016-06-18T09:55:15.643248Z   41 Query    rollback
相關文章
相關標籤/搜索