unListener简述
JUnit4中的RunListener类用来监听测试执行的各个阶段,由RunNotifier通知测试去运行。RunListener与RunNotifier之间的协作应用的是观察者模式,RunListener类充当观察者角色,RunNotifier充当通知者角色,有点类似于JDK中的事件监听器MouseListener在鼠标执行不同的操作时触发相应方法中封装的动作。RunListener监听的动作包括如下测试阶段:
- 所有测试开始前:调用testRunStarted()
- 所有测试结束后:调用testRunFinished()
- 测试套开始前:调用testSuiteStarted()
- 测试套结束后:调用testSuiteFinished()
- 原子测试方法开始前:调用testStarted()
- 原子测试方法结束后:调用testFinished()
- 原子测试被忽略:调用testIgnored()
- 测试执行失败或监听器自身抛出异常:调用testFailure()
- 原子测试方法因调用Assume类中的方法失败(非测试执行失败):调用testAssumptionFailure()
RunListener封装了测试执行过程处于这些阶段时需要做出的响应,另外提供了@ThreadSafe用来表明其所注解的监听器是线程安全的。
JUnit4自身已经提供了如下两个RunListener子类供系统调用,我们还可以根据测试实际需要扩展自己的RunListener。
- TextListener:以打印文本的形式处理测试各阶段的RunListener子类,打印操作由其类成员java.io.PrintStream执行
- SynchronizedRunListener:线程安全的RunListener子类,未使用@ThreadSafe修饰的监听器由该子类封装
Junit4在Result类中内置了一个私有内部类Listener用于实时统计测试执行信息,该内部类继承自RunListener但不对外提供系统调用。
RunListener源码分析
RunListener定义了9个空方法和1个注解,这里空方法的主要作用是分类各种测试事件并定义相应的回调接口,回调接口中的参数用于将数据传递给上层模块。由于各类测试事件发生的时机不同,所以RunListener中分别使用了Description、Result和Failure类封装回调接口需要传递给上层模块的数据。
- 关键代码
JUnit4.12版本增加了@ThreadSafe注解,JUnit4.13版本新增了testSuiteStarted()和testSuiteFinished()两个测试事件。去掉英文注释后的源码如下:
//org.junit.runner.notification
public class RunListener { //所有测试开始前被调用 public void testRunStarted(Description description) throws Exception { } //所有测试结束后被调用 public void testRunFinished(Result result) throws Exception { } //测试套执行前被调用 public void testSuiteStarted(Description description) throws Exception { } //测试套执行后被调用 public void testSuiteFinished(Description description) throws Exception { } //单个原子级测试执行前被调用 public void testStarted(Description description) throws Exception { } //单个原子级测试执行后被调用 public void testFinished(Description description) throws Exception { } //单个原子级测试失败时或监听器抛出异常时被调用,并且把测试失败信息写入到Failure类对象中 public void testFailure(Failure failure) throws Exception { } //原子级测试方法因调用Assume类中的方法失败(非测试执行失败),并将调用失败信息写入到Failure类对象中 public void testAssumptionFailure(Failure failure) { }
//当执行到被@Ignore修饰的原子级测试方法时调用 public void testIgnored(Description description) throws Exception { }
//被@ThreadSafe修饰的监听器是线程安全的 @Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface ThreadSafe { } }
- 相关类解析

