这里对BlockJUnit4ClassRunner中几个跟写单元测试最相关的几个方法进行分析
(1)构造方法
(2)createTest
(3)withPotentialTimeout
(5) withAfters
(6) methodBlock
(6) methodBlock
采用的是双向链表的数据结构。而Statement代表了一个操作,即单元测试中所要处理的一个环境。像在单元测试中所加的注解@Befores,@Afters等等都是Statement。Statement是个抽象类,所以操作都要重写evaluate方法,在继承statement的同时,做成双向的有序链表,这样就可以顺序的执行操作了。以RunBeforeTestMethod的源代码可以看到这点。
以上简单分析了Junit是如何执行单元测试用例的。
下一节介绍如何扩做自己的容器。以Spring提供实现为例。
(1)构造方法
public BlockJUnit4ClassRunner(Class<?> klass) throws InitializationError {
super(klass);
}
作用:是取得类的声名描述,即Class<?> klass
(2)createTest
protected Object createTest() throws Exception {
return getTestClass().getOnlyConstructor().newInstance();
}
作用:根据Class,创建测试用例类实例。
(3)withPotentialTimeout
protected Statement withPotentialTimeout(FrameworkMethod method,
Object test, Statement next) {
long timeout= getTimeout(method.getAnnotation(Test.class));
return timeout > 0 ? new FailOnTimeout(next, timeout) : next;
}
(4)withBefores
protected Statement withBefores(FrameworkMethod method, Object target,
Statement statement) {
List<FrameworkMethod> befores= getTestClass().getAnnotatedMethods(
Before.class);
return new RunBefores(statement, befores, target);
}
我们在单元测试时加注解@Befores,就是调用这个方法被执行的。
(5) withAfters
protected Statement withAfters(FrameworkMethod method, Object target,
Statement statement) {
List<FrameworkMethod> afters= getTestClass().getAnnotatedMethods(
After.class);
return new RunAfters(statement, afters, target);
}
我们在单元测试时加注解@Afters,就是调用这个方法被执行的。
(6) methodBlock
protected Statement methodBlock(FrameworkMethod method) {
Object test;
try {
test= new ReflectiveCallable() {
@Override
protected Object runReflectiveCall() throws Throwable {
return createTest();
}
}.run();
} catch (Throwable e) {
return new Fail(e);
}
Statement statement= methodInvoker(method, test);
statement= possiblyExpectingExceptions(method, test, statement);
statement= withPotentialTimeout(method, test, statement);
statement= withBefores(method, test, statement);
statement= withAfters(method, test, statement);
return statement;
}
(6) methodBlock
protected Statement methodBlock(FrameworkMethod method) {
Object test;
try {
test= new ReflectiveCallable() {
@Override
protected Object runReflectiveCall() throws Throwable {
return createTest();
}
}.run();
} catch (Throwable e) {
return new Fail(e);
}
Statement statement= methodInvoker(method, test);
statement= possiblyExpectingExceptions(method, test, statement);
statement= withPotentialTimeout(method, test, statement);
statement= withBefores(method, test, statement);
statement= withAfters(method, test, statement);
return statement;
}
分析这个类的原因,是想了解Junit的方法执行顺序是如何处理的。
采用的是双向链表的数据结构。而Statement代表了一个操作,即单元测试中所要处理的一个环境。像在单元测试中所加的注解@Befores,@Afters等等都是Statement。Statement是个抽象类,所以操作都要重写evaluate方法,在继承statement的同时,做成双向的有序链表,这样就可以顺序的执行操作了。以RunBeforeTestMethod的源代码可以看到这点。
public class RunBeforeTestMethod extends Statement {
private final Statement next;
private final Object testInstance;
private final Method testMethod;
private final TestContextManager testContextManager;
public RunBeforeTestMethod(Statement next, Object testInstance, Method testMethod,
TestContextManager testContextManager) {
this.next = next;
this.testInstance = testInstance;
this.testMethod = testMethod;
this.testContextManager = testContextManager;
}
@Override
public void evaluate() throws Throwable {
this.testContextManager.beforeTestMethod(this.testInstance, this.testMethod);
this.next.evaluate();
}
}
而前面提到的代码
Statement statement= methodInvoker(method, test);
statement= possiblyExpectingExceptions(method, test, statement);
statement= withPotentialTimeout(method, test, statement);
statement= withBefores(method, test, statement);
statement= withAfters(method, test, statement);
就是在整理各个操作间执行的先后顺序。
以上简单分析了Junit是如何执行单元测试用例的。
下一节介绍如何扩做自己的容器。以Spring提供实现为例。