使用RunWith註解改變JUnit的預設執行類,並實Listener在平時的單元測試
public class TestClass {
@Test public void t1(){}
}
JUnit允許使用者指定其它的單元測試執行類,只需要我們的測試執行類繼承類org.junit.runners.BlockJUnit4ClassRunner就可以了,Spring的執行類SpringJUnit4ClassRunner就是繼承了該類。我們平時用Spring也比較多,為了能夠更加方便的引用配置檔案,我們單元測試就使用了Spring實現的執行類。此時的單元測試執行類將會看起來是這樣:
[java] view plaincopy
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:/spring1.xml", "classpath*:/spring2.xml" })
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class })
@Transactional
public class TestClass {
@Inject
//這個類會在執行時被注入,這裡是按型別注入,如果想按名稱注入,需要加上@Named註解,如@Named("class1")
//實現類可以加上@Named("class1")註解,也可以是配置在配置檔案中的
Class1 class1;
@Test
public void t1(){}
}
以下分別對使用到的幾個註解進行解釋:
@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 plaincopy
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
@Documented
public @interface DBUnitTestData {
public String[] dataSetLocations();
}
2.編寫Listener,這個Listener的名字就定義為DBUnitTestExecutionListener.class:DBUnitTestExecutionListener.java
[java] view plaincopy
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListener;
public class DBUnitTestExecutionListener implements TestExecutionListener {
public void prepareTestInstance(TestContext testContext) throws Exception {
}
public void beforeTestClass(TestContext testContext) throws Exception {
// Nothing to do
}
public void afterTestClass(TestContext testContext) throws Exception {
// Nothing to do
}
public void beforeTestMethod(TestContext testContext) throws Exception {
DBUnitTestData dbUnitRefresh = testContext.getTestMethod().getAnnotation(DBUnitTestData.class);
if (dbUnitRefresh == null) {
return;
}
String[] dataSetLocations = dbUnitRefresh.dataSetLocations();
loadTestData(testContext, dataSetLocations);
}
public void afterTestMethod(TestContext testContext) throws Exception {
// Nothing to do
}
private void loadTestData(TestContext testContext, String[] dataSetLocations) {
if (dataSetLocations == null || dataSetLocations.length == 0) {
return;
}
for (String dataSetLocation : dataSetLocations) {
//Do what you want to do with the data set files
System.out.println(dataSetLocation);
}
}
}
3.將Listener實現類加入到測試類的@TestExecutionListeners裡面,在方法上面增加註解@DBUnitTestData,這個時候測試類將會是如下這樣:
[java] view plaincopy
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:/spring1.xml", "classpath*:/spring2.xml" })
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class,DBUnitTestExecutionListener.class })
@Transactional
public class TestClass {
@Inject
//這個類會在執行時被注入,這裡是按型別注入,如果想按名稱注入,需要加上@Named註解,如@Named("class1")
//實現類可以加上@Named("class1")註解,也可以是配置在配置檔案中的
Class1 class1;
@Test
@DBUnitTestData(dataSetLocations={"classpath:/testData/testData1.xml","classpath:/testData/testData2.xml"})
public void t1(){}
}
4.執行這個方法就可以看到@DBUnitTestData註解的資料檔案路徑給打印出來了。