接上一篇【Junit执行源码分析,junit是怎么跑起来的】 https://blog.csdn.net/Aqu415/article/details/127494898 这里我们接着分析

org.junit.runner.JUnitCore#run(org.junit.runner.Runner)

这个方法

public Result run(Runner runner) {

Result result = new Result();

RunListener listener = result.createListener();

notifier.addFirstListener(listener);

try {

notifier.fireTestRunStarted(runner.getDescription());

// @A

runner.run(notifier);

notifier.fireTestRunFinished(result);

} finally {

removeListener(listener);

}

return result;

}

@A:执行runer的run方法,会执行我们的待测试目标方法

上一篇说到 runner是 org.junit.internal.builders.AllDefaultPossibilitiesBuilder#runnerForClass得到的返回对象:

public Runner runnerForClass(Class testClass) throws Throwable {

List builders = Arrays.asList(

ignoredBuilder(),

annotatedBuilder(),

suiteMethodBuilder(),

junit3Builder(),

junit4Builder());

for (RunnerBuilder each : builders) {

Runner runner = each.safeRunnerForClass(testClass);

if (runner != null) {

return runner;

}

}

return null;

}

junit默认提供了几种Runner,比如听过的Junit3和熟悉的Junit4(其他的没听过 哈哈); 这里会决定返回哪一种 Runner; 从设计模式上来说这里运用的策略模式:每一种runner会根据目标测试类判解析是否需要自己来处理,如果是由自己来处理则返回一个Runner类;就好像说:嗯,你是我的菜,并把菜装在篮子里返回;

举个例,我们看看 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);

}

}

如果类上标注了 @TestCase注解,那么这个类就会由JUnit3执行

**我们看看JUnit4Builder **

public class JUnit4Builder extends RunnerBuilder {

@Override

public Runner runnerForClass(Class testClass) throws Throwable {

return new BlockJUnit4ClassRunner(testClass);

}

}

看代码JUnit4是一个兜底的方案,其他Runner不吃的菜全部由他来吃;嗯 了不起

BlockJUnit4ClassRunner

上面我们看到了JUnit4Builder 返回了一个BlockJUnit4ClassRunner对象;

BlockJUnit4ClassRunner继承了 ParentRunner,ParentRunner的run方法就是执行测试类方法的入口(上面标记@A的地方)。

org.junit.runners.ParentRunner#run

@Override

public void run(final RunNotifier notifier) {

EachTestNotifier testNotifier = new EachTestNotifier(notifier,

getDescription());

try {

// @A

Statement statement = classBlock(notifier);

// @B

statement.evaluate();

} catch (AssumptionViolatedException e) {

testNotifier.addFailedAssumption(e);

} catch (StoppedByUserException e) {

throw e;

} catch (Throwable e) {

testNotifier.addFailure(e);

}

}

@A:方法源码如下

org.junit.runners.ParentRunner#classBlock

protected Statement classBlock(final RunNotifier notifier) {

// @A1

Statement statement = childrenInvoker(notifier);

// @A2

if (!areAllChildrenIgnored()) {

statement = withBeforeClasses(statement);

statement = withAfterClasses(statement);

statement = withClassRules(statement);

}

return statement;

}

@A1:找到标记了 @Test注解的方法 @A1:把测试类里标注了 @BeforeClass(静态方法) 、@AfterClass(静态方法)等注解的方法找到并包装成 Statement对象,设计模式应该属于责任链模式,形成一个链式数据结构

@B 最终调用的方法是 org.junit.runners.ParentRunner#runChildren

private void runChildren(final RunNotifier notifier) {

final RunnerScheduler currentScheduler = scheduler;

try {

for (final T each : getFilteredChildren()) {

currentScheduler.schedule(new Runnable() {

public void run() {

// @C

ParentRunner.this.runChild(each, notifier);

}

});

}

} finally {

currentScheduler.finished();

}

}

@C:最终调用的是ParentRunner子类BlockJUnit4ClassRunner的runChild方法

org.junit.runners.BlockJUnit4ClassRunner#runChild

跟了一圈代码最终方法执行到 org.junit.runners.BlockJUnit4ClassRunner#runChild

@Override

protected void runChild(final FrameworkMethod method, RunNotifier notifier) { //@C0

Description description = describeChild(method);

// @C1

if (isIgnored(method)) {

notifier.fireTestIgnored(description);

} else {

// @C3

runLeaf(methodBlock(method), description, notifier); // @C2

}

}

@C0: method参数是通过org.junit.runners.ParentRunner#getFilteredChildren方法获得的,通过一连串分析,得知其是子类 org.junit.runners.BlockJUnit4ClassRunner#getChildren返回值

@Override

protected List getChildren() {

return computeTestMethods();

}

调用方法:

protected List computeTestMethods() {

return getTestClass().getAnnotatedMethods(Test.class);

}

清晰了:是把所有标记 @Test注解的方法获取到

@C1:被忽略的方法,不被执行

@C2: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);

statement = withRules(method, test, statement);

return statement;

}

这里跟上面ParentRunner行为差不多,会把目标类里标注了 @Before、@After的方法和目标方法串联起来,这里区别的是:ParentRunner是把标注了@BeforeClass、和@AfterClass的静态方法串联起来。

这里会返回一个Statement 对象,源码如下

protected Statement methodInvoker(FrameworkMethod method, Object test) {

return new InvokeMethod(method, test);

}

Statement 对象将方法和其对应的类关联起来,返回的是一个InvokeMethod对象;

@C3:runLeaf方法

protected final void runLeaf(Statement statement, Description description,

RunNotifier notifier) {

EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);

eachNotifier.fireTestStarted();

try {

// @D

statement.evaluate();

} catch (AssumptionViolatedException e) {

eachNotifier.addFailedAssumption(e);

} catch (Throwable e) {

eachNotifier.addFailure(e);

} finally {

eachNotifier.fireTestFinished();

}

}

@D:即执行上面Statement 的evaluate方法,最终即执行 InvokeMethod 类的evaluate方法;

public class InvokeMethod extends Statement {

private final FrameworkMethod testMethod;

private final Object target;

public InvokeMethod(FrameworkMethod testMethod, Object target) {

this.testMethod = testMethod;

this.target = target;

}

@Override

public void evaluate() throws Throwable {

testMethod.invokeExplosively(target);

}

}

这样就执行到我们的目标方法了。

不得不说初次来看代码很绕,不花点时间折腾调试还真摸不着头脑;但如果你能站在更高的角度,去思考完成这个功能所需的设计,也许就不觉得那么饶了; 核心我觉得还是面向对象的一些思想:封装、继承、多态;代码复用、设计模式等等

over~~

好文阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: