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

Rrr*_*Rrr 21 java logging unit-testing

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

public class A {

    private static final Log LOG = LogFactory.getLog(A.class);
Run Code Online (Sandbox Code Playgroud)

和用法:

} catch (Exception e) {
    LOG.error(e.getMessage(), e);
    throw e;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Car*_*ond 13

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

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


kap*_*kap 5

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

当然,您不想测试每个日志事件,我认为应该只测试 ERROR(而不是全部)。

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

我现在想到的有两个:

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

SLF4J 测试:不如 slf4jtesting 强大,并且似乎没有被开发,但可以很好地与现有代码配合使用。除了用于测试的记录器配置外,没有任何修改。

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

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);
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

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