【发布时间】:2018-12-06 14:34:07
【问题描述】:
我有一个使用 SLF4J 和 logback 作为底层记录器的 java 10 上运行的 spring boot 2 应用程序。
给定以下弹簧组件:
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
我已经探索了一些选项,但没有一个看起来“理想”但确实有效。
- 在测试类路径上提供一个日志返回配置文件,该文件将日志级别设置为至少跟踪这一类。
- 在 Spring 应用程序属性类中将此类的日志级别设置为
TRACE,并在 Spring 上下文中运行测试。 - 在测试类中创建一个设置并拆除,该类在测试执行期间以编程方式修改日志级别,然后在之后将其重置。
我目前的解决方案是让 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 配置远离测试类路径也意味着其他测试不关心日志记录不选择配置。
也就是说,感觉“奇怪”,我从未真正见过有人以这种方式使用 spring 测试(测试没有依赖关系且不直接依赖上下文的单个 bean)。该测试以计划 POJO 测试开始,不关心春天,感觉更“纯粹”,保持这种状态。
在尝试通过 SLF4J 测试对象的日志输出时,是否有适用的最佳实践?
【问题讨论】:
标签: java junit logback slf4j spring-boot-test