上次说完了MethodRule之后,是时候说说Statement这个东西是怎么回事了。
首先我们来看一下org.junit.runners.BlockJUnit4ClassRunner中执行测试的核心代码:
protected void runChild(FrameworkMethod method, RunNotifier notifier) {
EachTestNotifier eachNotifier= makeNotifier(method, notifier);
if (method.getAnnotation(Ignore.class) != null) {
eachNotifier.fireTestIgnored();
return;
}
eachNotifier.fireTestStarted();
try {
methodBlock(method).evaluate();
} catch (AssumptionViolatedException e) {
eachNotifier.addFailedAssumption(e);
} catch (Throwable e) {
eachNotifier.addFailure(e);
} finally {
eachNotifier.fireTestFinished();
}
}
而methodBlock()方法返回的就是Statement对象。它里面就只有一个接口方法:
package org.junit.runners.model;
/**
* Represents one or more actions to be taken at runtime in the course
* of running a JUnit test suite.
*/
public abstract class Statement {
/**
* Run the action, throwing a {@code Throwable} if anything goes wrong.
*/
public abstract void evaluate() throws Throwable;
}
注释很直白的说明了它就是负责执行动作以及抛出相应执行过程中的异常。那实际上有多少种statement的实现,而其各自的evaluate又是在干嘛的呢?我们今天就来探讨一下。我发现所有可以在junit内部定义的内部使用的Statement包括以下几个:
它们都是在org.junit.internal.runners.statements包里面。下面简单介绍它们做的东西:
类名 |
作用 |
ExpectedException |
用于检测标明期待出现错误的测试方法是否通过了测试(无异常抛出),或者抛出的异常和期待值不一样。 |
Fail |
直接出错,中断所有后续的步骤。 |
FailOnTimeout |
开一个线程来跑测试方法,并且通过Thread.join来判定该线程是否超时。如果出错或者超时都会认为是失败。 |
InvokeMethod |
通过映射机制执行不带参数的测试方法 |
RunAfters |
在执行完测试目标方法之后,尝试执行所有的@After和@AfterClass方法,并且把这个过程中的所有遇到的错误统一输出处理。注意@After方法是全部都会尝试执行一遍的,而不会因为中途遇到异常就会被中断。即使测试方法本身出现错误,@After和@AfterClass方法也会被执行一次! |
RunBefores |
尝试先运行所有@BeforeClass和@Before方法,和RunAfters不一样,只要途中遇到一个方法出错就会终止连锁执行行为。 |
为什么Statement我只是简单介绍一下呢?因为大部分的Statement将被MethodRule机制所代替,所以大家只要了解一下个概念及其功能就好了。
下次来复习一下4.1的@RunWith标记及自定义测试运行引擎的方法(主要是很不幸我之前的学习笔记弄丢了
)