我有几个类: 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中失败。但我不喜欢嘲笑所有这些方法的想法!它们仅用于记录。另外,每当我添加一些日志消息时,我都不想修复我的测试。
记录在那里非常有用,所以我根本不想删除它。但是仅仅为日志记录模拟方法看起来很奇怪。
我如何解决这个问题?
答案 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:你真的打算在你的代码中保留名为tagret
和sourse
的属性吗?