聊聊單元測試(三)——Spring Test+JUnit完美組合

本着「不寫單元測試的程序員不是好程序員」原則,我在堅持寫着單元測試,不敢說全部的Java web應用都基於Spring,但至少一半以上都是基於Spring的。
發現經過Spring進行bean管理後,作測試會有各類不足,
 
例如,不少人作單元測試的時候,還要在Before方法中,初始化Spring容器,致使容器被初始化屢次。
[java]  view plain  copy
 
 print?在CODE上查看代碼片派生到個人代碼片
  1. @Before  
  2.  public void init() {  
  3.       ApplicationContext ctx = new FileSystemXmlApplicationContext( "classpath:spring/spring-basic.xml");  
  4.       baseDao = (IBaseDao) ctx.getBean("baseDao");  
  5.       assertNotNull(baseDao);  
  6.  }    


在開發基於Spring的應用時,若是你還直接使用Junit進行單元測試,那你就錯過了Spring滿漢全席中最重要的一道硬菜。html

 
再說這道菜以前,咱們先來討論下,在基於Spring的javaweb項目中使用Junit直接進行單元測試有什麼不足
 
   1)致使屢次Spring容器初始化問題 

   根據JUnit測試方法的調用流程,每執行一個測試方法都會建立一個測試用例的實例並調用setUp()方法。因爲通常狀況下,咱們在setUp()方法中初始化Spring容器,這意味着若是測試用例有多少個測試方法,Spring容器就會被重複初始化屢次。雖然初始化Spring容器的速度並不會太慢,但因爲可能會在Spring容器初始化時執行加載Hibernate映射文件等耗時的操做,若是每執行一個測試方法都必須重複初始化Spring容器,則對測試性能的影響是不容忽視的; 

    /////////使用Spring測試套件,Spring容器只會初始化一次! 

    2)須要使用硬編碼方式手工獲取Bean 

    在測試用例類中咱們須要經過ctx.getBean()方法從Spirng容器中獲取須要測試的目標Bean,而且還要進行強制類型轉換的造型操做。這種乏味的操做迷漫在測試用例的代碼中,讓人以爲煩瑣不堪; 

    ////////使用Spring測試套件,測試用例類中的屬性會被自動填充Spring容器的對應Bean 
,無須在手工設置Bean! 
   
   3)數據庫現場容易遭受破壞 

    測試方法對數據庫的更改操做會持久化到數據庫中。雖然是針對開發數據庫進行操做,但若是數據操做的影響是持久的,可能會影響到後面的測試行爲。舉個例子,用戶在測試方法中插入一條ID爲1的User記錄,第一次運行不會有問題,第二次運行時,就會由於主鍵衝突而致使測試用例失敗。因此應該既可以完成功能邏輯檢查,又可以在測試完成後恢復現場,不會留下「後遺症」; 

    ////////使用Spring測試套件,Spring會在你驗證後,自動回滾對數據庫的操做,保證數據庫的現場不被破壞,所以重複測試不會發生問題! 

   4)不方便對數據操做正確性進行檢查 
    
    假如咱們向登陸日誌表插入了一條成功登陸日誌,但是咱們卻沒有對t_login_log表中是否確實添加了一條記錄進行檢查。通常狀況下,咱們多是打開數據庫,肉眼觀察是否插入了相應的記錄,但這嚴重違背了自動測試的原則。試想在測試包括成千上萬個數據操做行爲的程序時,如何用肉眼進行檢查? 

    ////////只要你繼承Spring的測試套件的用例類,你就能夠經過jdbcTemplate在同一事務中訪問數據庫,查詢數據的變化,驗證操做的正確性! 
 
 看完上面的內容,相信,你已經知道我說的硬菜是什麼了。
 
下面,讓咱們看看,使用Spring測試套件後,代碼是如何變優雅的。

1. 加入依賴包

  使用spring測試框架須要加入如下依賴包:java

  • JUnit 4 
  • Spring Test (Spring框架中的test包)
  • Spring 相關其餘依賴包(再也不贅述了,就是context等包)
 
若是使用maven,在基於spring的項目中添加以下依賴:
[html]  view plain  copy
 
 print?在CODE上查看代碼片派生到個人代碼片
  1. <dependency>  
  2.             <groupId>junit</groupId>  
  3.             <artifactId>junit</artifactId>  
  4.             <version>4.9</version>  
  5.             <scope>test</scope>  
  6.         </dependency>   
  7. <dependency>  
  8.             <groupId>org.springframework</groupId>  
  9.             <artifactId>spring-test</artifactId>  
  10.             <version> 3.2.4.RELEASE  </version>  
  11.             <scope>provided</scope>  
  12.         </dependency>   


 

2. 建立測試源目錄和包

  在此,推薦建立一個和src平級的源文件目錄,由於src內的類都是爲往後產品準備的,而此處的類僅僅用於測試。而包的名稱能夠和src中的目錄同名,這樣因爲在test源目錄中,因此不會有衝突,並且名稱又如出一轍,更方便檢索。這也是Maven的約定。程序員

 

三、建立測試類

1)基類,其實就是用來加載配置文件的 
 
[java]  view plain  copy
 
 print?在CODE上查看代碼片派生到個人代碼片
  1. @RunWith(SpringJUnit4ClassRunner.class)  //使用junit4進行測試  
  2. @ContextConfiguration   
  3. ({"/spring/app*.xml","/spring/service/app*.xml"}) //加載配置文件  
  4.   
  5. //------------若是加入如下代碼,全部繼承該類的測試類都會遵循該配置,也能夠不加,在測試類的方法上///控制事務,參見下一個實例  
  6. //這個很是關鍵,若是不加入這個註解配置,事務控制就會徹底失效!  
  7. //@Transactional  
  8. //這裏的事務關聯到配置文件中的事務控制器(transactionManager = "transactionManager"),同時//指定自動回滾(defaultRollback = true)。這樣作操做的數據纔不會污染數據庫!  
  9. //@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)  
  10. //------------  
  11. public class BaseJunit4Test {  
  12. }  



2)接着是咱們本身的測試類 
 
[java]  view plain  copy
 
 print?在CODE上查看代碼片派生到個人代碼片
  1. public class UserAssignServiceTest extends BaseJunit4Test{  
  2. @Resource  //自動注入,默認按名稱  
  3. private IBaseDao baseDao;  
  4. @Test   //標明是測試方法  
  5. @Transactional   //標明此方法需使用事務  
  6. @Rollback(false)  //標明使用完此方法後事務不回滾,true時爲回滾  
  7. public void insert( ) {  
  8.             String sql="insert into user(name,password) values(?,?)";  
  9.             Object[] objs=new Object[]{"00","000"};  
  10.             baseDao.insert( sql , objs );  
  11.             String sql1="select * from user where name=? and password=? ";  
  12.             List<Map<String,Object>> list=baseDao.queryForList( sql1 , objs );  
  13.             System.out.println(list);  
  14.             assertTrue(list.size( )>0);   
  15.          }  
  16. }  

原文:http://blog.csdn.net/shan9liang/article/details/40452469web

相關文章
相關標籤/搜索