Junit 源码解析(一)之junit运行容器
package org.junit.runner; public abstract class Runner implements Describable Runner是JUNIT的运行容器,它是各种Junit运行容器的父类。我们可以把它理解成web容器,spring容器,就是单元测试类所在运行环境。 我们在跑单元测试时,单元测试用例的生命周期就是由runner来控制的。这和其他容器一样。 首先是选择容器,在跑单元测试时,最先构建的是Runner容器。源代码如下: 见AllDefaultPossibilitiesBuilder下的public Runner runnerForClass(Class<?> testClass) throws Throwable@Override
public Runner runnerForClass(Class<?> testClass) throws Throwable { List<RunnerBuilder> builders= Arrays.asList( ignoredBuilder(), annotatedBuilder(), suiteMethodBuilder(), junit3Builder(), junit4Builder());for (RunnerBuilder each : builders) {
Runner runner= each.safeRunnerForClass(testClass); if (runner != null) return runner; } return null; }builders是容器的创建者,它是一个list,创建ignoredBuilder(),annotatedBuilder(),suiteMethodBuilder(),junit3Builder(),junit4Builder());
遍历builders,因为list是有序的,当某一个junit容器创建成功,则跳出循环,不再创建其他容器。而创建好的Runner容器就负责执行单元测试用例。 下面说一下各个容器的作用和特点 (1)IgnoredBuilder,public Runner runnerForClass(Class<?> testClass) {
if (testClass.getAnnotation(Ignore.class) != null) return new IgnoredClassRunner(testClass); return null; }当在你的单元测试类前面加@Ignore的时候,这个容器就会被创建。这个容器不会执行单元测试方法。
这也就是当我们有些单元测试用例类跑不过时,加类上面加注解@Ignore,通过忽略通过的原因。 (2)AnnotatedBuilder @Override public Runner runnerForClass(Class<?> testClass) throws Exception { RunWith annotation= testClass.getAnnotation(RunWith.class); if (annotation != null) return buildRunner(annotation.value(), testClass); return null; }在JUNIT已经提供了自己的容器,当在生产开发中,如果觉得JUNIT提供的容器已经不能满足需求时,可以自己创建个性化的容器。在类的声名加上注解RunWith,指定你自己创建容器。像在spring中,它提供了自己的单元测试容器。
请见Spring测试的基类AbstractJUnit4SpringContextTests,在它的类注解中加了RunWith,指定它的测试容器SpringJUnit4ClassRunner。 一般情况我们并不会用到这个容器。这里想说明的是JUNIT做为一个框架,它通过AnnotatedBuilder提供了可扩展的接口 (3)SuiteMethodBuilder 略 (4)JUnit3Builder public class JUnit3Builder extends RunnerBuilder { @Override public Runner runnerForClass(Class<?> testClass) throws Throwable { if (isPre4Test(testClass)) return new JUnit38ClassRunner(testClass); return null; }boolean isPre4Test(Class<?> testClass) {
return junit.framework.TestCase.class.isAssignableFrom(testClass); } }这是Junit的早期版本使用的容器,那时写单元测试类需要继承TestCase,现在我们不用再继承这个类了。为兼容老版本。当你的单元测试用例继承了TestCase这个容器就会被创建。isPre4Test方法判断你所写的测试用例类是否是TestCase的子类。记得好像3.8之后的版还是4.0之后的版就可以不用继承TestCase了。
(5)JUnit4Builder @Override public Runner runnerForClass(Class<?> testClass) throws Throwable { return new BlockJUnit4ClassRunner(testClass); }创建最新的Junit自带的测试容器。这个容器是我们现在最常用的,虽然我们并不了解它,但平常写的测试用例类都是在BlockJUnit4ClassRunner下运行的。由于版本原因,这里的BlockJUnit4ClassRunner是比较新容器。之前版本的容器是JUnit4ClassRunner,现在这个类已经打上@Deprecated注解,不再推荐使用。当然你也可以通过上面提到的RunWith来使用这个容器。
针对现在最常用BlockJUnit4ClassRunner,在下一个章节来看他的源码。