将slf4j重定向到字符串

Ela*_*ich 6 java logging slf4j

如何配置slf4j将所有记录的信息重定向到Java字符串?

这有时在单元测试中很有用,例如,测试在加载servlet时不会打印警告,或者确保从不使用禁用的SQL表.

ear*_*cam 5

有点晚了,但还是...

由于在单元测试时日志配置应该很容易替换,因此您只需配置为记录标准输出,然后在执行日志主题之前捕获它。然后将记录器设置为对除被测对象以外的所有对象保持静音。

@Test
public void test()
{
    String log = captureStdOut(() -> {
        // ... invoke method that shouldn't log
    });
    assertThat(log, is(emptyString()));
}



public static String captureStdOut(Runnable r)
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PrintStream out = System.out;
    try {
        System.setOut(new PrintStream(baos, true, StandardCharsets.UTF_8.name()));
        r.run();
        return new String(baos.toByteArray(), StandardCharsets.UTF_8);
    } catch (UnsupportedEncodingException e) {
        throw new RuntimeException("End of the world, Java doesn't recognise UTF-8");
    } finally {
        System.setOut(out);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果在测试中使用 slf4j 而不是 log4j,一个简单的log4j.properties

log4j.rootLogger=OFF, out
log4j.category.com.acme.YourServlet=INFO, out
log4j.appender.out=org.apache.log4j.ConsoleAppender
log4j.appender.out.layout=org.apache.log4j.PatternLayout
log4j.appender.out.layout.ConversionPattern=%-5p %c{1}:%L - %m%n
Run Code Online (Sandbox Code Playgroud)

或者,如果您不喜欢在单元测试中将配置作为外部依赖项,那么以编程方式配置 log4j:

//...

static final String CONSOLE_APPENDER_NAME = "console.appender";

private String pattern = "%d [%p|%c|%C{1}] %m%n";
private Level threshold = Level.ALL;
private Level defaultLevel = Level.OFF;

//...

public void configure()
{
    configureRootLogger();
    configureConsoleAppender();
    configureCustomLevels();
}


private void configureConsoleAppender()
{
    ConsoleAppender console = new ConsoleAppender();
    console.setName(CONSOLE_APPENDER_NAME);
    console.setLayout(new PatternLayout(pattern));
    console.setThreshold(threshold);
    console.activateOptions();
    Logger.getRootLogger().addAppender(console);
}


private void configureRootLogger()
{
    Logger.getRootLogger().getLoggerRepository().resetConfiguration();
    Logger.getRootLogger().setLevel(defaultLevel);
}
Run Code Online (Sandbox Code Playgroud)


Mik*_*eck 3

在我看来,你有两个选择。

首先,您可以实现一个自定义 Appender(取决于您使用的 slf4j 实现),它只需将每个记录的语句附加到 StringBuffer 中。在这种情况下,您可能必须保存对 StringBuffer 的静态引用,以便您的测试类可以访问它。

其次,您可以编写自己的 ILoggerFactory 和 Logger 实现。同样,您的记录器只会将所有消息附加到内部 StringBuffers,尽管在这种情况下您可能有多个缓冲区,每个日志级别一个。如果您这样做,您将有一个简单的方法来检索 Logger 实例,因为您拥有分发它们的工厂。