我们应该单独测试记录吗?

时间:2012-08-17 01:34:27

标签: java unit-testing logging

通常会在代码中看到日志记录功能:

public class A {

    private static final Log LOG = LogFactory.getLog(A.class);

和用法:

} catch (Exception e) {
    LOG.error(e.getMessage(), e);
    throw e;
}

但我从来没有看到过这样的代码的单一单元测试。

当然我测试抛出异常和异常类型,但是我应该编写测试来检查日志记录信息吗?我倾向于认为日志记录是系统行为的另一部分,所以它在逻辑上退出以在测试中覆盖它。

假设我应该覆盖它,意味着我应该更改我的原始代码以注入模拟日志并检查"错误"使用预期消息调用方法。但是,如果我的原始类是service并且它是由spring实例化的,该怎么办?我应该注入一些记录器以及其他依赖项吗?

6 个答案:

答案 0 :(得分:11)

您无法测试日志库。但值得测试的是,当抛出异常时,您的类会在正确的级别记录消息。您正在测试的是您的代码使用日志库做正确的事情。

要使上面的代码可测试,请使用依赖注入。这假设记录器实现了一个接口ILog。您可以将记录器作为构造函数参数传递给类A.然后测试代码将创建ILog的模拟实现,并将其传递给构造函数。上面的代码中没有显示异常是如何产生的,但可能是通过其他一些依赖对象。所以你也嘲笑它,并让它抛出异常。然后检查模拟ILog是否调用了error方法。也许您想要检查它记录的消息,但这可能会使测试代码变得脆弱。

答案 1 :(得分:2)

是的,我们应该在日志记录正在执行所需的操作时测试日志记录。例如,您在某些外部应用程序中有挂钩,可以扫描日志中的某些事件。在这种情况下,您当然希望确保完成日志记录。

当然你不想测试每个登录事件,我认为大多数情况下只应该测试ERROR(而不是所有的)。

使用现代日志框架(如SLF4j),您只需注入一个自定义处理程序,该事件处理程序将事件存储在内存中,然后可以对其进行断言。

现在我想到了其中两个:

SLF4JTesting:不需要修改日志记录配置,但需要注入可能导致修改代码的日志工厂。

SLF4J Test:没有slf4jtesting那么强大,似乎没有开发,但适用于现有代码。除了用于测试的记录器配置之外,没有任何修改。

使用SLF4J Test时,断言非常严格,并检查整个事件是否相等。在这种情况下,自定义匹配器可能很有趣:

public static Matcher<LoggingEvent> errorMessageContains(final String s) {
    return new TypeSafeMatcher<LoggingEvent>() {
        @Override
        public void describeTo(final Description description) {
            description.appendText(" type " + Level.ERROR + " should contain ")
                    .appendValue(s);
        }

        @Override
        protected void describeMismatchSafely(final LoggingEvent item, final Description mismatchDescription) {
            mismatchDescription.appendText(" was type ").appendValue(l)
                    .appendText(" message ").appendValue(item.getMessage());
        }

        @Override
        protected boolean matchesSafely(final LoggingEvent item) {
            return item.getLevel().equals(Level.ERROR)
                    && item.getMessage().contains(s);
        }
    };
}

这只会检查邮件是否包含文本,但如果相等则不会。因此,当修改消息以修正拼写错误或提供更多细节时,如果仍然包含必要部分,则测试不会中断。

答案 2 :(得分:1)

我不会单独测试除了调用您信任的库之外什么都不做的代码 你相信你的日志库吗?如果测试失败,是因为库中存在错误,还是因为您没有正确配置库?您是否关心测试配置?

答案 3 :(得分:1)

还有另一种方式:你可以模拟LogFactory!例如:

 $scope.getStyle = function(url){
  return {
    'background-image': "url(" + url + ")",
    'background-position': 'center center'
  }      
}
祝你好运!

答案 4 :(得分:1)

对于日志记录方案,我肯定会考虑进行单元测试。在测试时,请考虑代码失败时需要的信息。如果您遇到了实时问题,则希望确保自己有足够的信息来查找问题的原因。

避免过多的日志记录,因为调试时可能看不到树木穿过树林。

答案 5 :(得分:0)

如果日志记录是业务需求,并且将提供业务价值(即在发生故障时,诊断或分类问题),那么您应该将其视为任何其他要求。因此,您应该编写单元测试,而不是验证您的日志记录库是否正常工作,但要验证在预期的情况下,您的代码会记录它应该是什么。

有关此主题的更多信息:https://ardalis.com/logging-and-monitoring-are-requirements