1. 程式人生 > >使用RunWith註解改變JUnit的預設執行類,並實現自已的Listener

使用RunWith註解改變JUnit的預設執行類,並實現自已的Listener

 

zh

使用RunWith註解改變JUnit的預設執行類,並實現自已的Listener在平時的單元測試,如果不使用RunWith註解,那麼JUnit將會採用預設的執行類Suite執行,如下類:

[java] view plain copy

  1. public class TestClass {  
  2.     @Test public void  t1(){}  
  3. }  

JUnit允許使用者指定其它的單元測試執行類,只需要我們的測試執行類繼承類org.junit.runners.BlockJUnit4ClassRunner就可以了,Spring的執行類SpringJUnit4ClassRunner就是繼承了該類。我們平時用Spring也比較多,為了能夠更加方便的引用配置檔案,我們單元測試就使用了Spring實現的執行類。此時的單元測試執行類將會看起來是這樣:

[java] view plain copy

  1. @RunWith(SpringJUnit4ClassRunner.class)  
  2. @ContextConfiguration
    (locations = { "classpath*:/spring1.xml""classpath*:/spring2.xml" })  
  3. @TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class })  
  4. @Transactional  
  5. public class
     TestClass {  
  6.     @Inject  
  7.     //這個類會在執行時被注入,這裡是按型別注入,如果想按名稱注入,需要加上@Named註解,如@Named("class1")  
  8.     //實現類可以加上@Named("class1")註解,也可以是配置在配置檔案中的  
  9.     Class1 class1;  
  10.       
  11.     @Test   
  12.     public void  t1(){}  
  13. }  

以下分別對使用到的幾個註解進行解釋:

@RunWith:這個是指定使用的單元測試執行類,這裡就指定的是SpringJUnit4ClassRunner.class;

@ContextConfiguration:這個指定spring配置檔案所在的路徑,可以同時指定多個檔案;

@TestExecutionListeners:這個用於指定在測試類執行之前,可以做的一些動作,如這裡的DependencyInjectionTestExecutionListener.class,就可以對一測試類中的依賴進行注入,TransactionalTestExecutionListener.class用於對事務進行管理;這兩個都是Srping自帶的; 我們也可以實現自己的Listener類來完成我們自己的操作,只需要繼續類org.springframework.test.context.support.AbstractTestExecutionListener就可以了,具體可以參照DependencyInjectionTestExecutionListener.class的實現,後面我會貼出例項。 Listener實在實現類執行之前被執行、實現類的測試方法之前被執行,這與Listener的實現有關。

@Transactional:這裡的@Transactional不是必須的,這裡是和@TestExecutionListeners中的TransactionalTestExecutionListener.class配合使用,用於保證插入的資料庫中的測試資料,在測試完後,事務回滾,將插入的資料給刪除掉,保證資料庫的乾淨。如果沒有顯示的指定@Transactional,那麼插入到資料庫中的資料就是真實的插入了。

我們的單元測試,通常涉及到資料庫的操作,那我們就需要真實的從資料庫中讀取資料並進行邏輯處理,為了保證資料庫的乾淨,也為了保證測試資料的準確性與正確性,我們最好是在做測試之前插入我們自己準備的測試資料,然後在測試完成後,將資料刪除掉,這時我們就可以通過增加一個Listener,來準備我們需要的測試資料,並和上面的事務管理相結合,就不會真正的提交到資料庫中去了。

以下這個例項是一個簡單的Listener實現,只是功能是把我們配置在method上面的註解裡面的配置檔案路徑給打印出來,因為實現整合DBUnit並插入資料庫的程式碼比較多,這裡我就不貼出來了。1.首先我們需要準備一個註解,用來標識其帶的引數為測試準備的資料檔案:DBUnitTestData.Java

[java] view plain copy

  1. @Retention(RetentionPolicy.RUNTIME)  
  2. @Target(ElementType.METHOD)  
  3. @Inherited  
  4. @Documented  
  5. public @interface DBUnitTestData {  
  6.   
  7.     public String[] dataSetLocations();  
  8. }  

2.編寫Listener,這個Listener的名字就定義為DBUnitTestExecutionListener.class:DBUnitTestExecutionListener.java

[java] view plain copy

  1. import org.springframework.test.context.TestContext;  
  2. import org.springframework.test.context.TestExecutionListener;  
  3.   
  4. public class DBUnitTestExecutionListener implements TestExecutionListener {  
  5.   
  6.     public void prepareTestInstance(TestContext testContext) throws Exception {  
  7.     }  
  8.   
  9.     public void beforeTestClass(TestContext testContext) throws Exception {  
  10.         // Nothing to do  
  11.     }  
  12.   
  13.     public void afterTestClass(TestContext testContext) throws Exception {  
  14.         // Nothing to do  
  15.     }  
  16.   
  17.     public void beforeTestMethod(TestContext testContext) throws Exception {  
  18.         DBUnitTestData dbUnitRefresh = testContext.getTestMethod().getAnnotation(DBUnitTestData.class);  
  19.         if (dbUnitRefresh == null) {  
  20.             return;  
  21.         }  
  22.         String[] dataSetLocations = dbUnitRefresh.dataSetLocations();  
  23.         loadTestData(testContext, dataSetLocations);  
  24.     }  
  25.   
  26.     public void afterTestMethod(TestContext testContext) throws Exception {  
  27.         // Nothing to do  
  28.     }  
  29.   
  30.     private void loadTestData(TestContext testContext, String[] dataSetLocations) {  
  31.         if (dataSetLocations == null || dataSetLocations.length == 0) {  
  32.             return;  
  33.         }  
  34.         for (String dataSetLocation : dataSetLocations) {  
  35.             //Do what you want to do with the data set files  
  36.             System.out.println(dataSetLocation);  
  37.         }  
  38.     }  
  39.   
  40. }  

3.將Listener實現類加入到測試類的@TestExecutionListeners裡面,在方法上面增加註解@DBUnitTestData,這個時候測試類將會是如下這樣:

[java] view plain copy

  1. @RunWith(SpringJUnit4ClassRunner.class)  
  2. @ContextConfiguration(locations = { "classpath*:/spring1.xml""classpath*:/spring2.xml" })  
  3. @TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class,DBUnitTestExecutionListener.class })  
  4. @Transactional  
  5. public class TestClass {  
  6.     @Inject  
  7.     //這個類會在執行時被注入,這裡是按型別注入,如果想按名稱注入,需要加上@Named註解,如@Named("class1")  
  8.     //實現類可以加上@Named("class1")註解,也可以是配置在配置檔案中的  
  9.     Class1 class1;  
  10.       
  11.     @Test   
  12.     @DBUnitTestData(dataSetLocations={"classpath:/testData/testData1.xml","classpath:/testData/testData2.xml"})  
  13.     public void  t1(){}  
  14. }  

4.執行這個方法就可以看到@DBUnitTestData註解的資料檔案路徑給打印出來了。