2015-02-23 58 views
7

所有MyService方法都是事務性的。下面的JUnit測試,獲取項目的數量,節省了一個新的項目,並獲得項目的數量,以確保數已經增加,由1在非調試模式下,junit中的@un事件未按預期工作

public class MyTest extends ServiceTest{ 

    1. int countBefore = myService.getCount(); //return n 
    2. myService.add(item);      //item is really added to DB 
    3. int countAfter = myService.getCount(); //return n (sometimes n+1) 
} 

@Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.READ_COMMITTED) 
getCount(){…} 

@Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.SERIALIZABLE) 
add(){…} 

@Ignore 
@ContextConfiguration(locations = { "file:src/main/resources/xxx-context.xml", 
            "file:src/main/resources/xxx-data.xml", 
            "file:src/main/resources/xxx-services.xml" }) 
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = false) 
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, 
          DirtiesContextTestExecutionListener.class, 
          TransactionalTestExecutionListener.class, 
          TestListener.class}) 

public class ServiceTest extends AbstractUT{ 

@Ignore 
@RunWith(SpringJUnit4ClassRunner.class) 
@TestExecutionListeners({TestListener.class}) 
public class AbstractUT{ 

當調試(3.)返回n + 1這是我想要的。但是,在沒有調試的情況下運行測試時,我得到n

即使有時運行測試我得到n + 1和下次我得到n和比較兩個執行之間的標準輸出時,它看起來完全一樣。我已經啓用log4j.logger.org.springframework.transaction = TRACE,我可以看到:

Initializing transaction synchronization 
Getting transaction for MyService.getCount 
... 
Completing transaction for MyService.getCount 
Clearing transaction synchronization 

... 

Initializing transaction synchronization 
Getting transaction for MyService.add 
... 
Completing transaction for MyService.add 
Clearing transaction synchronization 

... 

Initializing transaction synchronization 
Getting transaction for MyService.getCount 
... 
Completing transaction for MyService.getCount 
Clearing transaction synchronization 

所以交易正在執行一個接一個,但怎麼可能(3)看不到保存的項目?

交易同治是建立在我的測試類按:https://stackoverflow.com/a/28657650/353985

我如何才能找到什麼錯誤? 謝謝!

+0

您是否使用''?無論如何看到我的回答[此鏈接](http://stackoverflow.com/a/25910635/3364187)。 – Xstian 2015-02-23 08:27:13

+0

絕對是的。 – redochka 2015-02-23 08:32:05

+0

你可以添加配置和你的TestClass嗎? – Xstian 2015-02-23 08:42:26

回答

3

有類似的問題,但在我的情況下,它沒有回滾。似乎你忘了添加@Transactional。從技術文檔(link

事務管理

在TestContext框架,交易由 TransactionalTestExecutionListener其默認配置管理, 即使你沒有明確你的 聲明@TestExecutionListeners測試班。但是,要啓用對事務的支持,必須在通過@ContextConfiguration語義加載的ApplicationContext 中配置PlatformTransactionManager Bean(詳細信息請參閱下面的 )。此外,您必須在 測試的類或方法級別聲明Spring的 @Transactional註釋。

這裏是上面的鏈接的示例。

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration 
@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false) 
@Transactional 
public class FictitiousTransactionalTest { 

@BeforeTransaction 
public void verifyInitialDatabaseState() { 
    // logic to verify the initial state before a transaction is started 
} 

@Before 
public void setUpTestDataWithinTransaction() { 
    // set up test data within the transaction 
} 

@Test 
// overrides the class-level defaultRollback setting 
@Rollback(true) 
public void modifyDatabaseWithinTransaction() { 
    // logic which uses the test data and modifies database state 
} 

@After 
public void tearDownWithinTransaction() { 
    // execute "tear down" logic within the transaction 
} 

@AfterTransaction 
public void verifyFinalDatabaseState() { 
    // logic to verify the final state after transaction has rolled back 
} 

}

+0

我注意到你說過你的方法有@Transactional,但我仍然必須將它們添加到我的方法級別以進行測試。 – kyla 2015-02-26 21:48:23

+0

即使通過在測試方法中添加@Transactional,我也會得到相同的行爲。 – redochka 2015-02-27 01:15:28

+0

您的交易傳播如何? – kyla 2015-02-27 01:40:19

0

溶液我發現至今通過測試是把斷言在afterTransaction方法

公共類MyTest的延伸ServiceTest {

@Test 
public void test(){ 
    1. int countBefore = myService.getCount(); //return n 
    2. myService.add(item);      //item is really added to DB 
} 
 
@AfterTransaction 
public void verifyFinalDatabaseState() { 
    3. int countAfter = myService.getCount(); //
            
 
  
             return n (sometimes n+1)
            
  
                //Now always return n+1 
} 
0

由於當前正在運行的交易記錄設置在test method level處,您有兩個選項:

  1. 你要麼刪除的測試方法,@Transactional,靠你的服務方法@Transactional邊界。這樣,當你撥打:

    int countBefore = myService.getCount(); 
    myService.add(item); 
    int countAfter = myService.getCount(); 
    

每個服務電話將會在一個孤立的事務中運行,就像它發生在運行時調用生產。

  • 您沖洗Hibernate會話,只需添加項之後:

    int countBefore = myService.getCount(); 
    myService.add(item); 
    transactionTemplate.execute(new TransactionCallback<Void>() { 
        @Override 
        public Company doInTransaction(TransactionStatus transactionStatus) { 
         entityManager.flush(); 
         return null; 
        } 
    }); 
    int countAfter = myService.getCount(); 
    
  • 甲HQL/JPQL計數查詢應觸發自動刷新模式的刷新,但是an SQL native query doesn't flush the Session

    +0

    已經嘗試過你的答案的兩個選項。 1-我的測試不是@ transactional, 2我沒有entityManager,我使用sessionFactory.getCurrentSession.flush() 仍然得到相同的奇怪行爲。到目前爲止,唯一可行的是在@ AfterTransaction中聲明。看到我的答案。 – redochka 2015-03-03 12:07:32

    +0

    您也可以使用Hibernate Session。按照我的建議嘗試'transactionTemplate'。 – 2015-03-03 12:35:26

    0

    我會在評論中提出這個問題,但由於我的聲望不允許,我只是試圖提供一個答案。

    您可能正在使用緩存計數查詢結果的ORM。根據add/getCount方法的實現方式以及ORM和數據源的配置,在第二次調用getCount時,您可能會獲得在第一次調用getCount期間獲得的緩存值。

    但是這並不能解釋爲什麼在調試模式下你總能得到正確的結果。

    +0

    我使用休眠,你的想法也來到我身上。如何解決休眠緩存? – redochka 2015-03-05 16:24:27

    +0

    看看這裏[Hibernate配置](https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/session-configuration.html)表3.5。我相信hibernate.cache.use_query_cache和hibernate.cache.use_second_level_cache會讓你感興趣。嘗試在休眠配置中將兩者設置爲false。 – 2015-03-09 20:36:55