JUnit4 源码阅读(一)
简介
JUnit 是一个Java开源单元测试框架。在1997年,由 Erich Gamma 和 Kent Beck 开发完成。其中 Erich Gamma是GoF(Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides)成员之一。
Java中的继承
,内部类
,注解
, 反射
,泛型
,异常
以及线程
在JUnit源码处处可见,阅读源码有助于加强我们的基础功底。同时,JUnit中使用到了许多的设计模式,如组合
,装饰
,职责链
,观察者
,模板方法
等等,有助于我们设计模式的学习和理解。阅读源码同时,我们可以学习大师们的编程习惯,使我们的代码更加安全,简洁,规范…两个字更美
.
JUnit体系结构
基本注解
注解基础知识, 请看:Java 反射和注解的一些总结
After
在测试方法执行后,要执行的方法。方法必须是公共非静态
AfterClass
在测试类执行后,需要执行的方法。方法必须是公共静态
Before
在测试方法执行前,要执行的方法。方法必须是公共非静态
BeforeClass
在测试类执行前,需要执行的方法。方法必须是公共静态
Ignore
测试方法,或者测试类被忽略
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface After {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterClass {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BeforeClass {
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Ignore {
/**
* The optional reason why the test is ignored.
*/
String value() default "";
}
Rule
作用于非静态的公共作用域或方法,用于定义方法的测试规则
RuleClass
作用域静态的公共作用域或方法,用于定义测试类的测试规则
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface Rule {
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface ClassRule {
}
Test
作用一个公共非静态的测试方法
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Test {
/**
* Default empty exception
*/
static class None extends Throwable {
private static final long serialVersionUID = 1L;
private None() {
}
}
Class<? extends Throwable> expected() default None.class;
long timeout() default 0L;
}
internal
执行类构建器builders
builders中是抽象RunnerBuilder
的几种实现,作用是基于我们的测试类(要测试的类)来构建对应的执行器Runner
,其中AllDefaultPossibilitiesBuilder
整合几种RunnerBuilder,用于根据测试类的信息(注解信息)来指定唯一的一个Builder来创建Runner。
public class AllDefaultPossibilitiesBuilder extends RunnerBuilder {
private final boolean canUseSuiteMethod;
public AllDefaultPossibilitiesBuilder(boolean canUseSuiteMethod) {
this.canUseSuiteMethod = canUseSuiteMethod;
}
@Override
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;
}
protected JUnit4Builder junit4Builder() {
return new JUnit4Builder();
}
protected JUnit3Builder junit3Builder() {
return new JUnit3Builder();
}
protected AnnotatedBuilder annotatedBuilder() {
return new AnnotatedBuilder(this);
}
protected IgnoredBuilder ignoredBuilder() {
return new IgnoredBuilder();
}
protected RunnerBuilder suiteMethodBuilder() {
if (canUseSuiteMethod) {
return new SuiteMethodBuilder();
}
return new NullBuilder();
}
}
首先是IgnoredBuilder
,如果测试有@Ignore
注解,产生的Runner是IgnoredClassRunner
, 该测试类的测试被忽略,不会执行,实际的执行run
方法,仅仅是一个测试忽略的通知Notifier
public