接上一篇【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<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;
}
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<FrameworkMethod> getChildren() {
return computeTestMethods();
}
调用方法:
protected List<FrameworkMethod> 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~~