自定義加載器
在我們的測(cè)試基類(lèi)中,我們使用了Spring-test提供的加載器
@RunWith(SpringJUnit4ClassRunner.class)
為了實(shí)現(xiàn)上文說(shuō)的效果,我們需要自定義自己的加載器
public class MyJUnit4ClassRunner extends SpringJUnit4ClassRunner{
public MyJUnit4ClassRunner(Class<?> clazz) throws InitializationError {
super(clazz);
}
}
查看一下SpringJUnit4ClassRunner的源碼煞躬,他告訴我們應(yīng)該怎么書(shū)寫(xiě)我們的加載器。下面是我們書(shū)寫(xiě)的加載器
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
public class MyJUnit4ClassRunner extends SpringJUnit4ClassRunner{
private Class<?> clazz;
public MyJUnit4ClassRunner(Class<?> clazz) throws InitializationError {
super(clazz);
this.clazz = clazz;
}
// 攔截 BeforeClass 事件
@Override
protected Statement withBeforeClasses(Statement statement) {
final Statement junitStatement = super.withBeforeClasses(statement);
return new Statement() {
@Override
public void evaluate() throws Throwable {
System.out.println("Before Class: " + clazz.getName());
junitStatement.evaluate();
}
};
}
// 攔截每一個(gè)方法的 Before 事件
@Override
protected Statement withBefores(final FrameworkMethod frameworkMethod, Object testInstance, Statement statement) {
final Statement junitStatement = super.withAfters(frameworkMethod, testInstance, statement);
return new Statement() {
@Override
public void evaluate() throws Throwable {
System.out.println("測(cè)試類(lèi): " + clazz.getName() + "--測(cè)試方法: " + frameworkMethod.getName() + " 開(kāi)始執(zhí)行绪颖!");
junitStatement.evaluate();
}
};
}
// 截獲測(cè)試類(lèi)的 AfterClass 事件
@Override
protected Statement withAfterClasses(Statement statement) {
final Statement junitStatement = super.withAfterClasses(statement);
return new Statement() {
@Override
public void evaluate() throws Throwable {
junitStatement.evaluate();
System.out.println("After Class: " + clazz.getName());
}
};
}
// 截獲每一個(gè)測(cè)試方法的 after 事件
@Override
protected Statement withAfters(final FrameworkMethod frameworkMethod, Object testInstance, Statement statement) {
final Statement junitStatement = super.withAfters(frameworkMethod, testInstance, statement);
return new Statement() {
@Override
public void evaluate() throws Throwable {
System.out.println("測(cè)試類(lèi): " + clazz.getName() + "--測(cè)試方法: " + frameworkMethod.getName() + " 執(zhí)行結(jié)束欠母!");
junitStatement.evaluate();
}
};
}
}
使用加載器
修改我們的測(cè)試基類(lèi)即可
//@RunWith(SpringJUnit4ClassRunner.class)
@RunWith(MyJUnit4ClassRunner.class)
進(jìn)行測(cè)試,會(huì)有如下的輸出
測(cè)試類(lèi): com.yun.spring.UserAssignServiceTest--測(cè)試方法: insert 執(zhí)行結(jié)束仔戈!
測(cè)試類(lèi): com.yun.spring.UserAssignServiceTest--測(cè)試方法: insert 開(kāi)始執(zhí)行关串!
自定義監(jiān)聽(tīng)器
public class DBUnitTestExecutionListener implements TestExecutionListener {
@Override
public void beforeTestClass(TestContext testContext) throws Exception {
}
@Override
public void prepareTestInstance(TestContext testContext) throws Exception {
}
/**
* 在執(zhí)行測(cè)試操作之前
*/
@Override
public void beforeTestMethod(TestContext testContext) throws Exception {
System.out.println(this.getClass().getName() + "--" + testContext.getTestMethod().getName() + " 測(cè)試開(kāi)始");
}
@Override
public void afterTestMethod(TestContext testContext) throws Exception {
System.out.println(this.getClass().getName() + "--" + testContext.getTestMethod().getName() + " 測(cè)試結(jié)束");
}
@Override
public void afterTestClass(TestContext testContext) throws Exception {
}
}
使用監(jiān)聽(tīng)器
修改上文中的BaseJunit4Test類(lèi)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({
"classpath:test-hcm-context.xml",
"classpath:test-hcm-jpa.xml",
"classpath:test-hcm-servlet.xml",
"classpath:test-hcm-memcache.xml"})
// 這個(gè)非常關(guān)鍵,如果不加入這個(gè)注解配置监徘,事務(wù)控制就會(huì)完全失效晋修!
@Transactional
// 這里的事務(wù)關(guān)聯(lián)到配置文件中的事務(wù)控制器(transactionManager = "transactionManager"),同時(shí)
// 指定自動(dòng)回滾(defaultRollback = true)凰盔。這樣做操作的數(shù)據(jù)才不會(huì)污染數(shù)據(jù)庫(kù)墓卦!
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@TestExecutionListeners( {
DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DBUnitTestExecutionListener.class })
public class BaseJunit4Test {
}
@TestExecutionListeners中的參數(shù)書(shū)寫(xiě)我們自定義的監(jiān)聽(tīng)器來(lái)完成某些操作
TestRule的使用
Rule是一個(gè)用于測(cè)試單元類(lèi)中定義一個(gè)域的標(biāo)注。雖然叫Rule廊蜒,但是仍然起攔截器/Interceptor的作用——即在運(yùn)行測(cè)試的前后添加一些有用的代碼趴拧。這里沒(méi)有使用,有興趣自行查看一下文檔山叮。
預(yù)告
下一步我們將介紹hamcrest的使用方法