0

我想为我运行的每个 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 测试用例的线程除外)也可以在日志文件中找到?

4

0 回答 0