测试日志输出 Java Spring

Testing Log Output Java Spring

我有一个 spring boot 2 应用程序 运行ning on java 10 使用 SLF4J 和 logback 作为底层记录器。

给定以下 spring 分量:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class MyClass {

    private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);

    public void hello() {
        // more logic...
        LOG.trace("World");
    }
}

以及希望验证日志输出的测试(想象一个更复杂的场景,其中日志将包含变量和上下文信息)或者生成日志消息的事实被认为是关键的。

import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.test.rule.OutputCapture;

import static org.hamcrest.Matchers.containsString;

public class MyClassTest {

    private final MyClass myClass = new MyClass();

    @Rule
    public final OutputCapture outputCapture = new OutputCapture();

    @Test
    public void successShouldLogSuccessMessages() {
        myClass.hello();
        outputCapture.expect(containsString("World"));
    }
}

要通过此测试,必须将日志级别设置为 TRACE。我注意到一些不可预知的行为,其中测试要么失败要么通过,具体取决于测试的顺序 运行 - 参见 Seemingly Random Test Failure With Maven & Spring Boot 2 When A WebFluxTest Is Introduced

我探索了一些选项,none 看起来 "ideal" 但确实有效。

  1. 在测试 class 路径上提供一个日志返回配置文件,该文件将日志级别设置为至少跟踪这个 class。
  2. 在 spring 应用程序属性 class 中将此 class 的日志级别设置为 TRACE 并且 spring 中的测试 运行 ] 上下文。
  3. 在测试中创建设置并拆除 class,它在测试执行期间以编程方式修改日志级别,然后在测试执行后重置它。

我目前的解决方案是让 Spring 完成配置记录器的工作,并使测试成为 spring 上下文测试(并确保它 运行 快速只加载我关心的一个 bean)如下:

@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.profiles.active=test")
@ContextConfiguration(classes = MyClass.class)
public class MyClassTest {

    private final MyClass myClass = new MyClass();

    @Rule
    public final OutputCapture outputCapture = new OutputCapture();

    @Test
    public void successShouldLogSuccessMessages() {
        myClass.hello();
        outputCapture.expect(containsString("World"));
    }
}

其中application-test.properties的内容是:

logging.level.com.example.MyClass=TRACE

这个解决方案有效,它不需要我以编程方式使用记录器或将 logback 配置放在 class 路径上,这使得一切都与底层日志框架完全无关,并使 logback 配置远离test classpath 也意味着其他不关心日志记录的测试不会获取配置。

也就是说,感觉"odd",我从来没有真正看到有人用这种方式使用spring测试(测试没有依赖关系和不直接依赖上下文的单个bean)。该测试作为一个计划 POJO 测试开始使用,不关心 spring 并且感觉更 "pure" 它仍然如此。

尝试通过 SLF4J 测试对象的日志输出时是否有适用的最佳实践?

您的方法是测试您当前的日志记录配置日志,而不是发送到日志系统的内容。

您可以 by writing your own appender or mocking out the SLF4J implementation. You could even fail the test from within your custom appender if something incorrect gets logged, 而不是 OutputCapture 规则。我建议创建您自己的 @Rule 来添加您自己的测试附加程序,然后它可以执行您想要的任何自定义逻辑来检查匹配器或确保记录正确的数据。