2010-11-12 60 views
34

我沒有問題測試我的DAO和服務,但是當我測試INSERT s或UPDATE s我想回滾事務並且不影響我的數據庫。如何在JUnit中使用Spring測試服務時回滾數據庫事務?

我在我的服務中使用@Transactional來管理事務。我想知道,是否有可能知道事務是否可以正常工作,但回滾它以防止更改數據庫?

這是我的測試:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = "classpath:/META-INF/spring.cfg.xml") 
@TransactionConfiguration(defaultRollback=true) 
public class MyServiceTest extends AbstractJUnit38SpringContextTests { 
    @Autowired 
    private MyService myService; 

    @BeforeClass 
    public static void setUpClass() throws Exception { 
    } 

    @AfterClass 
    public static void tearDownClass() throws Exception { 
    } 

    @Test 
    public void testInsert(){ 
     long id = myService.addPerson("JUNIT"); 
     assertNotNull(id); 
     if(id < 1){ 
      fail(); 
     } 
    } 
} 

的問題是,這個測試將失敗,因爲事務已rollbacked,但插入是OK! 如果我刪除@TransactionConfiguration(defaultRollback=true),則測試通過但新記錄將插入到數據庫中。

@Test 
@Transactional 
@Rollback(true) 
public void testInsert(){ 
    long id = myService.addPerson("JUNIT"); 
assertNotNull(id); 
if(id < 1){ 
     fail(); 
    } 
} 

現在可以正確測試通過,但回滾被忽略並且記錄被插入到數據庫中。 很明顯,我在myService中用@Transactional註解了方法addPerson()。 爲什麼回滾被忽略?

+0

很好的問題+1 :-) – 2013-12-13 10:52:48

回答

28

你需要事務邊界延伸到你的測試方法的邊界。您可以通過註釋測試方法(或整個測試類)作爲@Transactional做到這一點:

@Autowired SessionFactory sf; 

@Test 
@Transactional 
public void testInsert(){ 
    myService.addPerson("JUNIT"); 
    sf.getCurrentSession().flush(); 
    sf.getCurrentSession().doWork(... check database state ...); 
} 
+0

嗨,現在測試通過,但回滾被忽略。我有@Transactional通過「testAddPerson」和「addPerson」。 – blow 2010-11-12 17:11:32

+0

如果我從myService中刪除@Transactional,那麼測試中沒有活動事務,所以我認爲@Transactional在「testAddPerson」不起作用... – blow 2010-11-12 17:13:40

+5

@blow:我只注意到你已經擴展了AbstractJUnit38SpringContextTests。由於您使用'@ RunWith'進行JUnit 4測試,因此不需要它。 – axtavt 2010-11-12 17:29:41

2

退房

http://static.springsource.org/spring/docs/2.5.x/reference/testing.html

第8.3.4節特別

Spring有一些類進行測試,將包裹每個測試的交易,所以DB沒有改變。如果你想要,你也可以改變這個功能。

編輯 - 根據您的更多相關信息,您可能想看看

AbstractTransactionalJUnit38SpringContextTests在

http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/context/junit38/AbstractTransactionalJUnit38SpringContextTests.html

+0

嗨,我有更多的信息。 – blow 2010-11-12 16:56:23

+0

@blow - 我更新了我的答案。 – hvgotcodes 2010-11-12 17:01:01

+0

謝謝,這很有用,我在我的實現中發現了一個小問題。現在我有另一個問題,回滾被忽略 – blow 2010-11-12 17:14:58

0

如果:

@Test 
@Transactional 
public void testInsert(){ 
    long id=myService.addPerson("JUNIT"); 
    assertNotNull(id); 
    if(id<1){ 
     fail(); 
    } 
} 

您也可以使用這種方法來確保數據回滾之前正確寫入你的

myService.addPerson("JUNIT"); 

方法被註釋爲@Transactional你會得到一些不同的種類或錯誤試圖解決這個問題。所以你最好只測試DAO方法。

1

使用下面的類之前註釋:

@TransactionConfiguration(transactionManager = "txManager",defaultRollback = true) 
@Transactional 

這裏txManager是應用程序上下文的事務管理器。

這裏txManager是來自application context的事務管理器的實例或bean id。

<!-- Transaction Manager --> 
    <bean id="txManager" 
      class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 

    <tx:annotation-driven transaction-manager="txManager" /> 

添加您的代碼中setUp()方法,這將在試驗開始和最後的收官代碼應放在teatDown()方法將在最後執行的執行。或者也可以使用@Before@After註釋來代替它。