0

我有几个类:StateProcessorState。我想为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实例传递给process方法,因为这个类真的很复杂,而且构建它需要很多行代码。所以,我想传递用 Mockito 创建的模拟对象。根据主要逻辑,我只需要模拟 getTarget() 方法。但是在state.getTagret().getName()state.getSourse().toString()处的 NPE 执行将失败。但我不喜欢嘲笑所有这些方法的想法!它们仅用于记录。此外,我不想每次添加一些日志消息时都修复我的测试。

日志记录在那里非常有用,所以我根本不想删除它。但是嘲笑只用于记录的方法看起来很奇怪。

我该如何解决这个问题?

4

3 回答 3

1

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

 Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);
于 2012-04-18T16:03:41.593 回答
1

你所拥有的是一个经典的 Demeter 违反定律,这是一个用于模拟问题的教科书案例。

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

于 2012-04-18T16:17:27.317 回答
0

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

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

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

PS:你真的打算在你的代码tagret中保留命名属性吗?sourse

于 2012-04-18T15:52:33.240 回答