Spring Test 和 JUnit的結合

使用Spring做單元測試的不足

例如,很多人做單元測試的時候,還要在Before方法中,初始化Spring容器,導致容器被初始化多次。

@Before  
 public void init() {  
      ApplicationContext ctx = new FileSystemXmlApplicationContext( "classpath:spring/spring-basic.xml");  
      baseDao = (IBaseDao) ctx.getBean("baseDao");  
      assertNotNull(baseDao);  
 }    

1. 導致多次Spring容器初始化問題

根據(jù)JUnit測試方法的調(diào)用流程,每執(zhí)行一個測試方法都會創(chuàng)建一個測試用例的實例并調(diào)用setUp()方法。由于一般情況下,我們在setUp()方法中初始化Spring容器,這意味著如果測試用例有多少個測試方法,Spring容器就會被重復初始化多次。雖然初始化Spring容器的速度并不會太慢,但由于可能會在Spring容器初始化時執(zhí)行加載Hibernate映射文件等耗時的操作,如果每執(zhí)行一個測試方法都必須重復初始化Spring容器,則對測試性能的影響是不容忽視的;

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

2. 需要使用硬編碼方式手工獲取Bean

在測試用例類中我們需要通過ctx.getBean()方法從Spirng容器中獲取需要測試的目標Bean,并且還要進行強制類型轉換的造型操作。這種乏味的操作迷漫在測試用例的代碼中,讓人覺得煩瑣不堪;

使用Spring測試套件,測試用例類中的屬性會被自動填充Spring容器的對應Bean ,無須在手工設置Bean

3. 數(shù)據(jù)庫現(xiàn)場容易遭受破壞

測試方法對數(shù)據(jù)庫的更改操作會持久化到數(shù)據(jù)庫中。雖然是針對開發(fā)數(shù)據(jù)庫進行操作,但如果數(shù)據(jù)操作的影響是持久的,可能會影響到后面的測試行為。舉個例子,用戶在測試方法中插入一條ID為1的User記錄,第一次運行不會有問題,第二次運行時,就會因為主鍵沖突而導致測試用例失敗。所以應該既能夠完成功能邏輯檢查,又能夠在測試完成后恢復現(xiàn)場,不會留下“后遺癥”;

使用Spring測試套件,Spring會在你驗證后,自動回滾對數(shù)據(jù)庫的操作,保證數(shù)據(jù)庫的現(xiàn)場不被破壞,因此重復測試不會發(fā)生問題

4. 不方便對數(shù)據(jù)操作正確性進行檢查

假如我們向登錄日志表插入了一條成功登錄日志,可是我們卻沒有對t_login_log表中是否確實添加了一條記錄進行檢查。一般情況下,我們可能是打開數(shù)據(jù)庫,肉眼觀察是否插入了相應的記錄,但這嚴重違背了自動測試的原則。試想在測試包括成千上萬個數(shù)據(jù)操作行為的程序時,如何用肉眼進行檢查?

只要你繼承Spring的測試套件的用例類,你就可以通過jdbcTemplate在同一事務中訪問數(shù)據(jù)庫,查詢數(shù)據(jù)的變化,驗證操作的正確性!

使用Spring測試套件后,代碼是如何變優(yōu)雅的。

1. 加入依賴包

使用spring的測試框架需要加入以下依賴包:

  • JUnit 4
  • Spring Test (Spring框架中的test包)
  • Spring 相關其他依賴包(不再贅述了,就是context等包)

如果使用maven,在基于spring的項目中添加如下依賴:

<dependency>  
            <groupId>junit</groupId>  
            <artifactId>junit</artifactId>  
            <version>4.9</version>  
            <scope>test</scope>  
        </dependency>   
<dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-test</artifactId>  
            <version> 3.2.4.RELEASE  </version>  
            <scope>provided</scope>  
</dependency> 

2. 創(chuàng)建測試源目錄和包

在此,推薦創(chuàng)建一個和src平級的源文件目錄,因為src內(nèi)的類都是為日后產(chǎn)品準備的,而此處的類僅僅用于測試。而包的名稱可以和src中的目錄同名,這樣由于在test源目錄中,所以不會有沖突,而且名稱又一模一樣,更方便檢索。這也是Maven的約定。

3. 創(chuàng)建測試類

1)基類,其實就是用來加載配置文件的

@RunWith(SpringJUnit4ClassRunner.class)  //使用junit4進行測試  
@ContextConfiguration   
({"/spring/app*.xml","/spring/service/app*.xml"}) //加載配置文件  
  
//------------如果加入以下代碼,所有繼承該類的測試類都會遵循該配置,也可以不加,在測試類的方法上///控制事務,參見下一個實例  
//這個非常關鍵,如果不加入這個注解配置,事務控制就會完全失效!  
//@Transactional  
//這里的事務關聯(lián)到配置文件中的事務控制器(transactionManager = "transactionManager"),同時//指定自動回滾(defaultRollback = true)。這樣做操作的數(shù)據(jù)才不會污染數(shù)據(jù)庫!  
//@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)  
//------------  
public class BaseJunit4Test {  
}  

2)接著是我們自己的測試類

public class UserAssignServiceTest extends BaseJunit4Test{  
@Resource  //自動注入,默認按名稱  
private IBaseDao baseDao;  
@Test   //標明是測試方法  
@Transactional   //標明此方法需使用事務  
@Rollback(false)  //標明使用完此方法后事務不回滾,true時為回滾  
public void insert( ) {  
            String sql="insert into user(name,password) values(?,?)";  
            Object[] objs=new Object[]{"00","000"};  
            baseDao.insert( sql , objs );  
            String sql1="select * from user where name=? and password=? ";  
            List<Map<String,Object>> list=baseDao.queryForList( sql1 , objs );  
            System.out.println(list);  
            assertTrue(list.size( )>0);   
         }  
}  
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容