脱离开发工具使用junit运行一个测试类
本文以最基础的BlockJUnit4ClassRunner junit内置对象介绍
实例化一个被测试对象 并且被测试类必须具备无参数构造方法 并且只能有一个无参数构造方法
import org.junit.runner.JUnitCore;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
public class JunitExample {
public static void main(String[] args) throws InitializationError {
JUnitCore core = new JUnitCore();
// core.run(new SpringJUnit4ClassRunner(CheckServiceTest.class));
core.run(new BlockJUnit4ClassRunner(CheckServiceTest.class));
}
}
组件介绍
org.junit.runner.JUnitCore#run(org.junit.runner.Runner)
org.junit.runners.BlockJUnit4ClassRunner
junit默认的基础执行器
org.junit.runner.notification.RunNotifier
private final List<RunListener> listeners = new CopyOnWriteArrayList<RunListener>();
private volatile boolean pleaseStop = false;
管理监听列表和终止信号
org.junit.runner.Runner
public abstract Description getDescription();
public abstract void run(RunNotifier notifier);
public int testCount() {
return getDescription().testCount();
}
定义执行扩展点 和 测试描述信息管理
org.junit.runner.Description
private final Collection<Description> fChildren = new ConcurrentLinkedQueue<Description>();
private final String fDisplayName;
private final Serializable fUniqueId;
private final Annotation[] fAnnotations;
private volatile /* write-once */ Class<?> fTestClass;
测试类相关信息的载体
org.junit.runner.Result.Listener
org.junit.runner.notification.RunListener
org.junit.runners.model.Statement
public abstract void evaluate() throws Throwable;
就一个抽象方法 提供了实际执行器的扩展点
org.junit.runners.model.RunnerScheduler
单测任务调度管理
几段代码
runner.run(notifier);
内部实例化执行单元org.junit.runners.model.Statement的实现类 ,以evaluate方法实现实际任务提交的动作等其他的实现逻辑,以返回的实例化对象的evaluate显示调用来触发实际的后续job提交和执行逻辑
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()); 声明测试执行开始 实例化org.junit.runner.notification.RunNotifier.SafeNotifier 触发钩子函数的钩子testRunStarted 并run
runner.run(notifier); 执行器的run 实际单元测试执行逻辑
notifier.fireTestRunFinished(result); 声明测试执行完成
} finally {
removeListener(listener);
}
return result;
}
org.junit.runners.ParentRunner#run
@Override
public void run(final RunNotifier notifier) {
EachTestNotifier testNotifier = new EachTestNotifier(notifier, 声明 org.junit.internal.runners.model.EachTestNotifier
getDescription());
try {
Statement statement = classBlock(notifier); 获取org.junit.runners.model.Statement 对象 抽象类封装单元执行的能力提供 提供触发的抽象方法
statement.evaluate(); 触发实际执行单侧逻辑 org.junit.runners.ParentRunner#runChildren
} catch (AssumptionViolatedException e) {
testNotifier.addFailedAssumption(e);
} catch (StoppedByUserException e) {
throw e;
} catch (Throwable e) {
testNotifier.addFailure(e);
}
}
org.junit.runners.ParentRunner#classBlock
protected Statement classBlock(final RunNotifier notifier) {
Statement statement = childrenInvoker(notifier);
if (!areAllChildrenIgnored()) {
statement = withBeforeClasses(statement);
statement = withAfterClasses(statement);
statement = withClassRules(statement);
}
return statement;
}
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() {
ParentRunner.this.runChild(each, notifier);
}
});
}
} finally {
currentScheduler.finished();
}
}
ParentRunner.this.runChild(each, notifier); 决定实际的runner的具体执行 (见main函数入口传入的runner类)
org.junit.runners.BlockJUnit4ClassRunner#runChild
@Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
Description description = describeChild(method);
if (isIgnored(method)) {
notifier.fireTestIgnored(description);
} else {
runLeaf(methodBlock(method), description, notifier);
}
}
实例化被测试类对象 并构建 InvokeMethod 对象赋值被测试方法和实例
org.junit.runners.BlockJUnit4ClassRunner#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;
}
实际单元测试以evaluate 最终的反射来完成
org.junit.internal.runners.statements.InvokeMethod
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);
}
}
org.junit.runners.model.FrameworkMethod#invokeExplosively
public Object invokeExplosively(final Object target, final Object... params)
throws Throwable {
return new ReflectiveCallable() {
@Override
protected Object runReflectiveCall() throws Throwable {
return method.invoke(target, params);
}
}.run();
}
其他
org.junit.runners.model.RunnerScheduler 单元测试job调度
org.junit.runners.BlockJUnit4ClassRunner#methodBlock 子节点 实际执行逻辑构建
创建被测试类的实例化对象 org.junit.internal.runners.statements.InvokeMethod 赋值method和target
org.junit.runners.model.FrameworkMethod#invokeExplosively 完成方法的反射调用
method.invoke(target, params)