测试结果捕捉阶段(返回 Fail 或 Error 并显示)
通过以下代码,我们可以看出失败由第一个 catch 子句捕获,并交由 addFailure 方法处理,而错误由第三个 catch 子句捕获,并交由 addError 方法处理。
图 20. 失败处理函数代码

图 21. 失败处理流程图

JUnit 执行测试方法,并在测试结束后将失败和错误信息通知给所有的 test listener 。其中 addFailure、addError、endTest、startTest 是 TestListener 接口的四大方法,而 TestListener 涉及到 Observer 设计模式。
我们尝试看看 addFailure 方法的代码:
图 22. addFailure 方法的代码

此处代码将产生的失败对象加入到了 fFailures,可联系 图 2,此处的结果在程序退出时作为测试总体成功或失败的判断依据。而在 for 循环中,TestResult 对象循环遍历观察者(监听器)列表,通过调用相应的更新方法,更新所有的观察者信息,这部分代码也是整个 Observer 设计模式架构的重要部分。
根据以上描述,JUnit 采用 Observer 设计模式使得 TestResult 与众多测试结果监听器通过接口 TestListenner 达到松耦合,使 JUnit 可以支持不同的使用方式。目标对象(TestResult)不必关心有多少对象对自身注册,它只是根据列表通知所有观察者。因此,TestResult 不用更改自身代码,而轻易地支持了类似于 ResultPrinter 这种监听器的无限扩充。目前,已有文本界面、图形界面和 Eclipse 集成组件三种监听器,用户完全可以开发符合接口的更强大的监听器。
出于安全考虑,cloneListeners() 使用克隆机制取出监听器列表:
return (Vector)fListeners.clone();
}
TestResult 的 addFailure 进一步调用 ResultPrinter 的 addFailure:
图 23. ResultPrinter 的 addFailure 函数代码

这里并没有将错误信息输出,而只是输出了错误类型:“ F “。错误信息由图 14 中的:
统一输出。
这些设计细节皆可以由 TestRunner 的实现者自己掌握。
总结
鉴于 JUnit 目前在测试领域的显赫地位,以及 JUnit 实现代码本身编写的简洁与艺术性,本文的详尽分析无论对于测试开发的实践运用、基于 JUnit 的高层框架的编写、以及设计模式与 Java 语言高级特征的学习都具有多面的重要意义。