Junit 源码解析(二)

本文分析了JUnit测试框架中BlockJUnit4ClassRunner类的关键方法,包括测试用例实例化、执行前后置条件、超时处理等,揭示了JUnit测试方法的执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里对BlockJUnit4ClassRunner中几个跟写单元测试最相关的几个方法进行分析

(1)构造方法
	public BlockJUnit4ClassRunner(Class<?> klass) throws InitializationError {
super(klass);
}
作用:是取得类的声名描述,即Class<?> klass

(2)createTest
protected Object createTest() throws Exception {
return getTestClass().getOnlyConstructor().newInstance();
}
作用:根据Class,创建测试用例类实例。
(3)withPotentialTimeout
	protected Statement withPotentialTimeout(FrameworkMethod method,
Object test, Statement next) {
long timeout= getTimeout(method.getAnnotation(Test.class));
return timeout > 0 ? new FailOnTimeout(next, timeout) : next;
}
(4)withBefores
	protected Statement withBefores(FrameworkMethod method, Object target,
Statement statement) {
List<FrameworkMethod> befores= getTestClass().getAnnotatedMethods(
Before.class);
return new RunBefores(statement, befores, target);
}
我们在单元测试时加注解@Befores,就是调用这个方法被执行的。

(5) withAfters
	protected Statement withAfters(FrameworkMethod method, Object target,
Statement statement) {
List<FrameworkMethod> afters= getTestClass().getAnnotatedMethods(
After.class);
return new RunAfters(statement, afters, target);
}
我们在单元测试时加注解@Afters,就是调用这个方法被执行的。
(6) 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);
return statement;
}


(6) 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);
return statement;
}
分析这个类的原因,是想了解Junit的方法执行顺序是如何处理的。
采用的是双向链表的数据结构。而Statement代表了一个操作,即单元测试中所要处理的一个环境。像在单元测试中所加的注解@Befores,@Afters等等都是Statement。Statement是个抽象类,所以操作都要重写evaluate方法,在继承statement的同时,做成双向的有序链表,这样就可以顺序的执行操作了。以RunBeforeTestMethod的源代码可以看到这点。

public class RunBeforeTestMethod extends Statement {

private final Statement next;

private final Object testInstance;

private final Method testMethod;

private final TestContextManager testContextManager;

public RunBeforeTestMethod(Statement next, Object testInstance, Method testMethod,
TestContextManager testContextManager) {
this.next = next;
this.testInstance = testInstance;
this.testMethod = testMethod;
this.testContextManager = testContextManager;
}

@Override
public void evaluate() throws Throwable {
this.testContextManager.beforeTestMethod(this.testInstance, this.testMethod);
this.next.evaluate();
}

}
而前面提到的代码
		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);
就是在整理各个操作间执行的先后顺序。


以上简单分析了Junit是如何执行单元测试用例的。
下一节介绍如何扩做自己的容器。以Spring提供实现为例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值