statement = withAfters(method, test, statement);
statement = withRules(method, test, statement);
return statement;
}
前面的几行代码是在生成test 对象,而test对象的类型则是我们待测试的class,接下来追进methodInvoker方法:
protected Statement methodInvoker(FrameworkMethod method, Object test) {
return new InvokeMethod(method, test);
}
可见,我们生成的Statement实例为InvokeMethod,我们看下其eva luate方法:
testMethod.invokeExplosively(target);
invokeExplosively函数做的事情就是对target对象调用testMethod方法。而前面我们说过,这个testMethod在BlockJUnit4ClassRunner中就是被@Test所标注的方法,此时,我们终于找到了@Test方法是在哪里被调用的了。别急,我们接着刚才的函数继续分析:
statement = possiblyExpectingExceptions(method, test, statement);
statement = withPotentialTimeout(method, test, statement);
statement = withBefores(method, test, statement);
statement = withAfters(method, test, statement);
statement = withRules(method, test, statement);
我们可以看到,statement不断的在变形,而通过withBefores,withRules这些函数的名字我们可以很容易猜到,这里就是在处理@Before,@Rule等注解的地方,我们以withBefores为例:
protected Statement withBefores(FrameworkMethod method, Object target,
Statement statement) {
List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
Before.class);
return befores.isEmpty() ? statement : new RunBefores(statement,
befores, target);
}
这个函数里首先拿到了所有被@Before标注的方法,将其封装为RunBefores,我们看下其构造函数和
public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) {
this.next = next;
this.befores = befores;
this.target = target;
}
public void eva luate() throws Throwable {
for (FrameworkMethod before : befores) {
before.invokeExplosively(target);
}
next.eva luate();
}
很是明了,eva luate执行时,首先将before方法全部invoke来执行,然后才调用原始statement的eva luate方法。其余几个函数与此类似,感兴趣可以继续查看。
如此,我们就明白了runLeaf方法的第一个参数Statement的由来,接下来就看下这个runLeaf方法做了什么,runLeaf在ParentRunner中有默认的实现:
protected final void runLeaf(Statement statement, Description description,
RunNotifier notifier) {
EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
eachNotifier.fireTestStarted();
try {
statement.eva luate();
} catch (AssumptionViolatedException e) {
eachNotifier.addFailedAssumption(e);
} catch (Throwable e) {
eachNotifier.addFailure(e);
} finally {
eachNotifier.fireTestFinished();
}
}
非常简单,直接执行了statement的eva luate方法,需要注意的是这里的statement实例不一定是什么了,有可能是RunBefores,也有可能是RunAfters,这就和被测试类中的注解有关了。
讲到这里,还记得前面我们说过的存档A吗?我们回到存档A:
protected Statement classBlock(final RunNotifier notifier) {
Statement statement = childrenInvoker(notifier);
if (!areAllChildrenIgnored()) {
statement = withBeforeClasses(statement);
statement = withAfterClasses(statement);
statement = withClassRules(statement);
}
return statement;
}
刚刚存档后所发生的一起,其实就是在执行Statement statement = childrenInvoker(notifier)
这个代码。换句话说,childrenInvoker的作用就是将所有需要执行的测试用例用一个Statement封装起来。进而点燃这个Statement,就会触发所有的测试用例。但同样需要注意到被if语句包围的代码,我们又看到了熟悉的语句,Statement还在被不断的转换,但此时是在类的层面,withBeforeClasses函数操作的就是@BeforeClass注解了:
protected Statement withBeforeClasses(Statement statement) {
List<FrameworkMethod> befores = testClass
.getAnnotatedMethods(BeforeClass.class);
return befores.isEmpty() ? statement :
new RunBefores(statement, befores, null);
}
需要注意的是这回RunBefores的第三个参数为null,说明被@BeforeClass注解的方法只能是st