测试日志输出Java Spring

时间:2018-06-27 16:04:51

标签: java junit logback slf4j spring-boot-test

我有一个使用SLF4J在Java 10上运行的spring boot 2应用程序,并使用logback作为基础记录器。

给出以下弹簧组件:

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

我已经探索了几种选择,虽然似乎没有一个“理想的”选择,但确实可行。

  1. 在测试类路径上提供一个日志配置文件,该文件将日志级别设置为至少跟踪该类。
  2. 在spring应用程序属性类中将此类的日志级别设置为TRACE,然后在spring上下文中运行测试。
  3. 在测试类中创建一个设置并进行分类,该类会在测试执行过程中以编程方式修改日志级别,然后在之后将其重置。

我目前拥有的解决方案是让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配置放在类路径上,这使所有内容与底层日志框架完全不可知,并且使logback配置远离测试类路径也意味着其他测试不在乎日志记录不会获取配置。

也就是说,感觉“很奇怪”,我从未真正看到有人使用过这种弹簧测试(测试没有依赖性且不直接依赖上下文的单个bean)。该测试最初是一项计划性的POJO测试,无需对弹簧进行任何保养,但感觉仍然如此“纯正”。

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

1 个答案:

答案 0 :(得分:1)

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

您可以通过编写自己的附加程序或模拟SLF4J实现来intercept the logging,而不是OutputCapture规则。如果记录了一些不正确的信息such as an error,您甚至可能无法从自定义附加程序中通过测试。我建议您创建自己的@Rule,以添加自己的测试附加程序,该程序可以执行您想要检查匹配器或确保记录正确数据的任何自定义逻辑。