(1). 概述
一个功能模块,如果能通过单元测试全部覆盖所有的业务逻辑,那么,质量自然就能得到提升. 出于好奇,研究下Junit的单元测试,首先要找到入口,当我们在IDEA中,直接运行Junit时,实际上,IDEA是安装了Junit的插件来着的,最终的入口类为:JUnitCore.
(2). JUnit4Builder
package org.junit.internal.builders;
import org.junit.runner.Runner;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.RunnerBuilder;
public class JUnit4Builder extends RunnerBuilder {
// 1. IDEA会回调该方法,传递要测试的类,并通过:BlockJUnit4ClassRunner进行包装.
// testClass = help.lixin.test.service.IHelloService
@Override
public Runner runnerForClass(Class<?> testClass) throws Throwable {
return new BlockJUnit4ClassRunner(testClass);
}
}
(3). BlockJUnit4ClassRunner
package org.junit.runners;
public class BlockJUnit4ClassRunner
// ******************************************************
// 1. 继承于父类:ParentRunner
// ******************************************************
extends ParentRunner<FrameworkMethod> {
// klass 为我们要测试的类
public BlockJUnit4ClassRunner(Class<?> klass) throws InitializationError {
super(klass);
} // end BlockJUnit4ClassRunner
}
(4). ParentRunner
public abstract class ParentRunner<T> extends Runner implements Filterable,
Sortable {
private final TestClass fTestClass;
private Filter fFilter= null;
private Sorter fSorter= Sorter.NULL;
// 1. testClass为要测试的类
protected ParentRunner(Class<?> testClass) throws InitializationError {
// *************************************************************
// 2. 通过TestClass对被测试的类(help.lixin.test.service.IHelloService)进行包裹
// TestClass内部会收集方法上的注解/属性的注解等信息.
// *************************************************************
fTestClass= new TestClass(testClass);
validate();
} // end ParentRunner
// 2. 验证类上所有的信息.
private void validate() throws InitializationError {
List<Throwable> errors= new ArrayList<Throwable>();
collectInitializationErrors(errors);
if (!errors.isEmpty())
throw new InitializationError(errors);
} // end validate
}
(5). JUnitCore
public class JUnitCore {
// 定义:运行后的结果监听
private RunNotifier fNotifier;
// 1. 构建器
public JUnitCore() {
fNotifier = new RunNotifier();
} // end JUnitCore
// **************************************************************
// 2. IDEA会回调该方法
// Runner == BlockJUnit4ClassRunner
// **************************************************************
public Result run(Runner runner) { //
// 3. 创建返回结果
Result result= new Result();
// 4. 创建监听器
RunListener listener= result.createListener();
// 5. 为fNotifier配置监听器
fNotifier.addFirstListener(listener);
try {
// 6. 开始测试运行,典型的观察者模式
fNotifier.fireTestRunStarted(runner.getDescription());
// *************************************
// 7. 调用:BlockJUnit4ClassRunner.run方法.
// *************************************
runner.run(fNotifier);
// 8. 运行测试用例结束
fNotifier.fireTestRunFinished(result);
} finally {
removeListener(listener);
}
return result;
} // end run
}
(6). ParentRunner.run
public abstract class ParentRunner<T>
extends Runner
implements Filterable, Sortable {
public void run(final RunNotifier notifier) {
EachTestNotifier testNotifier= new EachTestNotifier(notifier,getDescription());
try {
// ********************************************************
// 1. 创建Statement
// ********************************************************
Statement statement= classBlock(notifier);
statement.evaluate();
} catch (AssumptionViolatedException e) {
testNotifier.fireTestIgnored();
} catch (StoppedByUserException e) {
throw e;
} catch (Throwable e) {
testNotifier.addFailure(e);
}
} //end run
// 2. 创建: Statement,典型的责任链模式
protected Statement classBlock(final RunNotifier notifier) {
// 2.1 创建着包裹我们最终要调用的业务
Statement statement= childrenInvoker(notifier);
// 2.2 @BeforeClass
statement= withBeforeClasses(statement);
// 2.3 @AfterClass
statement= withAfterClasses(statement);
return statement;
} // end classBlock
}
(7). 总结
Junit用起来虽然很简单,但是,它的框架设计得还是不错来着的.