2014-02-28 32 views
3

我想測試一個通過在循環中調用DAO將數據插入到表中的服務方法。該服務的方法都添加了Unittest使用REQUIRES_NEW的事務方法並始終強制回滾

@Transactional(propagation = Propagation.REQUIRES_NEW) 

的單元測試調用服務的方法,並標註了

@Transactional 

現在我想告訴大家,它應該總是在做一個回滾事務結束。我不想在testruns之後手動清理數據庫。

@Rollback和EntityManager.getTransaction()。setRollbackOnly()不起作用。我認爲原因是註釋和setRollbackOnly()僅適用於由test-method創建的事務,而不是由service-method創建的事務。

有誰知道如何解決?

+0

模擬DAO,手動注入一個新構建的服務,並測試該方法。您不需要Spring上下文或事務來進行單元測試服務。 –

+0

這就是我現在正在做的事情。但無論如何,我仍然想知道是否可以將事務設置爲rollbackonly。 – treeno

+0

如果你這樣做,你不需要回滾任何東西,因爲你不會有交易。 'new Service(mockDao).callMethod()'不會啓動一個事務,所以沒有什麼可以回滾的。 –

回答

0

我不認爲有可能輕鬆回滾REQUIRES_NEW事務。 SpringTest啓動一個事務,它可以回滾它開始的事務。但不是內部開始的交易。

所以你要麼回退到REQUIRED,要麼編寫你的測試,即使他們提交也能正常工作。如果選擇後者,則可以通過randomization實現測試隔離。

0

您可以創建一個可控的模擬實現org.springframework.transaction.PlatformTransactionManager委託給真正的只有一個區別,它可以選擇標記一個新的事務爲只讀。類似的東西,如果使用基於java的上下文配置:

... 
public class DaoTest { 
... 
@Autowired 
Dao _dao; 
@Autowired 
MockPlatformTransactionManager _transactionManager; 
... 
@Test 
@Transactional 
public void testSomeAction() throws Exception 
{ 
    try (AutoCloseable ignored = _transactionManager.withRollBack()) 
    { 
     _dao.someAction(); 
    } 
} 
... 
interface MockPlatformTransactionManager extends PlatformTransactionManager 
{ 
    AutoCloseable withRollBack(); 
} 
... 
// Somewhere in the @Configuration class 
@Bean 
MockPlatformTransactionManager transactionManager() 
{ 
    // an instance of real TM is adapted to become a MockPlatformTransactionManager 
    return new MockPlatformTransactionManager() 
    { 
     private final PlatformTransactionManager _delegate = 
      // TODO: same transaction manager as before 
      new DataSourceTransactionManager(dataSource()); 
     private boolean shouldRollBack = false; 

     @Override 
     public TransactionStatus getTransaction(final TransactionDefinition definition) 
      throws TransactionException 
     { 
      final TransactionStatus transaction = _delegate.getTransaction(definition); 
      if (shouldRollBack) 
       transaction.setRollbackOnly(); 
      return transaction; 
     } 

     @Override 
     public void commit(final TransactionStatus status) throws TransactionException 
     { 
      _delegate.commit(status); 
     } 

     @Override 
     public void rollback(final TransactionStatus status) throws TransactionException 
     { 
      _delegate.rollback(status); 
     } 

     @Override 
     public AutoCloseable withRollBack() 
     { 
      shouldRollBack = true; 
      return new AutoCloseable() 
      { 
       @Override 
       public void close() throws Exception 
       { 
        shouldRollBack = false; 
       } 
      }; 
     } 
    }; 
} 
相關問題