(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用起来虽然很简单,但是,它的框架设计得还是不错来着的.