单元测试和记录

时间:2012-04-18 15:30:22

标签: java junit mocking

我有几个类: StateProcessor State 。 我想为方法 StateProcessor.process(State)编写测试。 这种方法的逻辑非常简单,但它包含大量的日志消息。

logger.info(state.getSourse().toString());
if (state.getTarget() == Target.A) {
 logger.info(state.getCreationTime());
 service.doSmth(state);
} else {
 logger.info(state.getTagret().getName());
 service.doOtherStff(state);
}

我不想将真正的 State 实例传递给进程方法,因为这个类非常复杂,需要大量代码才能构建它。所以,我想传递用Mockito创建的模拟对象。根据主要逻辑,我只需要模拟getTarget()方法。但是执行将在 state.getTagret()。getName() state.getSourse()。toString()的NPE中失败。但我不喜欢嘲笑所有这些方法的想法!它们仅用于记录。另外,每当我添加一些日志消息时,我都不想修复我的测试。

记录在那里非常有用,所以我根本不想删除它。但是仅仅为日志记录模拟方法看起来很奇怪。

我如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

考虑模拟DEEP。这将导致每个方法调用返回模拟而不是null并阻止NPE。

 Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);

答案 1 :(得分:1)

你所拥有的是一个经典的Law of Demeter违规行为,这是一个用于嘲笑问题的教科书案例。

作为替代方案,请考虑将整个State对象记录在一个位置 - 例如在'if'块之前 - 并覆盖toString()方法以输出您需要查看的所有内容。然后你不需要取消引用每个字段并模拟每个方法。

答案 2 :(得分:0)

您可以将所有日志记录调用封装在if (!test) {}块中,并注入test属性。

或者您可以将它们放入if (logger.isInfoEnabled()) {}块并配置禁用信息的日志记录,或者为isInfoEnabled()注入一个返回false的模拟记录器。

但是日志记录是代码的关键部分。因此,如果您真的想测试它不会在生产中爆炸,您应该在生产代码中测试空值,或者证明这些属性可能永远不会返回null,并注入一个不返回null的模拟。

PS:你真的打算在你的代码中保留名为tagretsourse的属性吗?