我想为我运行的每个 JUnit 测试创建一个日志,每个都有自己的文件。
实际上,我昨天已经在 Logback 的SiftingAppender的帮助下做到了。
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
public class CustomJUnitTestRule implements AfterEachCallback, BeforeEachCallback {
@Override
public void beforeEach(ExtensionContext extensionContext) throws Exception {
Class<?> testClass = extensionContext.getTestClass().get();
AnnotatedElement annotatedElement = extensionContext.getElement().get();
Method method = extensionContext.getTestMethod().get();
String methodName = method.getName();
DisplayName displayName = testClass.getAnnotation(DisplayName.class);
String topic = displayName.value();
boolean annotationPresent = annotatedElement.isAnnotationPresent(Order.class);
int order = -1;
if (annotationPresent) {
Order orderAnnotation = annotatedElement.getAnnotation(Order.class);
order = orderAnnotation.value();
}
String fileName = String.format("%s-%02d-%s", topic, order, methodName);
MDC.put("testId", fileName);
}
@Override
public void afterEach(ExtensionContext extensionContext) throws Exception {
MDC.remove("testId");
}
}
带有示例 logback.xml
<configuration>
<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
<!-- in the absence of the class attribute, it is assumed that the
desired discriminator type is
ch.qos.logback.classic.sift.MDCBasedDiscriminator -->
<discriminator>
<key>testId</key>
<defaultValue>unknown</defaultValue>
</discriminator>
<sift>
<appender name="FILE-${userid}" class="ch.qos.logback.core.FileAppender">
<file>${testId}.log</file>
<append>false</append>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d [%thread] %level %mdc %logger{35} - %msg%n</pattern>
</layout>
</appender>
</sift>
</appender>
<root level="DEBUG">
<appender-ref ref="SIFT" />
</root>
</configuration>
和一个简单的测试
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@DisplayName("abc")
public class ABCTest {
@Test
@Order(1)
public void xxxTest() {
// ...
}
}
乍一看,它正在按预期工作。
但是,由于它使用 MDC 在后台工作,这本质上是线程有界的,这使得我的一些单元测试(创建多个线程)无法按预期工作。
我可以创建一个 logback 的 appender,它不是 MDC 绑定的,而是全局的,以便不同线程中的所有日志(运行 jUnit 测试用例的线程除外)也可以在日志文件中找到?