【问题标题】:unit tests and logging单元测试和日志记录
【发布时间】:2012-04-18 15:30:22
【问题描述】:

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

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

我该如何解决这个问题?

【问题讨论】:

  • 您不能配置测试环境以切断所有logger.info 消息,同时让您的开发人员显示它们吗?
  • 对不起,我没明白你的意思。日志记录在当前时刻被禁用。但我无法删除所有这些 logger.info 行
  • 我的意思是第一个回答的状态

标签: java junit mocking


【解决方案1】:

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

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

【讨论】:

  • 这正是我需要的!工作正常!我一直在寻找一些魔法,就是这样!
【解决方案2】:

你有一个经典的Law of Demeter违规,这是一个模拟问题的教科书案例。

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

【讨论】:

    【解决方案3】:

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

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

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

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

    【讨论】:

    • 用“if”包装日志记录是个不错的主意。但这会弄乱代码。代码 sn-p 是虚构的,因此属性名称不是真实的。
    猜你喜欢
    • 2010-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多