任何测试都有两个部分:让它发生和衡量你得到了正确的结果。
故障注入
最简单的答案是已经提到的那个,即设置cacheFileName
为一个永远不会存在的文件。在这种情况下,这可能是最实际的答案。
但是,要导致诸如 的任意条件IOException
,您真正想要的是故障注入。这会强制您的代码出现错误,而不会强制您检测源代码。这里有一些方法可以做到这一点:
- 模拟对象您可以使用工厂方法来创建覆盖的
ObjectOutputStream
或FileOutputStream
. 在测试代码中,实现会IOException
在您想要的时候抛出,而在生产代码中不会修改正常行为。
- 依赖注入为了将您的 Mock 对象放在正确的位置,您可以使用Spring或Seam等框架将适当的对象“注入”到正在执行工作的类中。您可以看到这些框架甚至对将要注入的对象具有优先级,因此在单元测试期间您可以使用测试对象覆盖生产对象。
- Aspect Oriented Programming你可以使用 AOP 将错误注入到正确的位置,而不是完全改变代码的结构。例如,使用AspectJ ,您可以定义一个切入点,您希望从中抛出异常,并让Advice抛出所需的异常。
Java 上的故障注入还有其他答案;例如,一个名为AProbe的产品很早以前就开创了 C 语言中可以称为 AOP 的东西,他们也有一个 Java 产品。
验证
抛出异常是一个好的开始,但您还必须验证您得到了正确的结果。假设您拥有的代码示例是正确的,您想要验证您是否记录了该异常。上面有人提到为您的记录器使用 Mock 对象,这是一个可行的选择。您还可以在此处使用 AOP 来捕获对记录器的调用。
我假设记录器是log4j;为了解决类似的问题,我实现了自己的 log4j appender,它捕获 log4j 输出:我专门只捕获ERROR
and FATAL
,在这种情况下,它们很可能是有趣的日志消息。appenderlog4j.xml
在测试运行期间被引用并被激活以捕获错误日志输出。这本质上是一个模拟对象,但我不必重组所有得到 log4j 的代码Logger
。