如何在log4j2中为自定义记录器编写单元测试

时间:2015-02-09 18:32:41

标签: java unit-testing logging log4j log4j2

我创建了一些自定义记录器,其中一些级别覆盖了Log4J2中的自定义记录器。我按照http://logging.apache.org/log4j/2.x/manual/customloglevels.html的指南进行了操作。

我需要创建一些单元测试来验证事件是否按照正确的自定义级别和配置进行了注册。

我很欣赏任何关于如何开始的提示。非常感谢。

3 个答案:

答案 0 :(得分:5)

这里有你在我的一个JUnit测试中完成的工作。

1-创建一个自定义appender,其中包含内存中的消息列表。

package com.example.appender;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;

/**
 * @author carrad
 * 
 */
@Plugin(name = "TestAppender", category = "Core", elementType = "apender", printObject = true)
public class TestAppender extends AbstractAppender {

    private static final long serialVersionUID = 8047713135100613185L;
    private List<String> messages = new ArrayList<String>();

    protected TestAppender(String name, Filter filter, Layout<? extends Serializable> layout) {
        super(name, filter, layout);
    }

    @Override
    public void append(LogEvent event) {
        getMessages().add(event.getMessage().toString());
    }


    @PluginFactory
    public static TestAppender createAppender(@PluginAttribute("name") String name,
            @PluginElement("Layout") Layout<? extends Serializable> layout, 
            @PluginElement("Filter") final Filter filter,
            @PluginAttribute("otherAttribute") String otherAttribute) {
        if (name == null) {
            LOGGER.error("No name provided for TestAppender");
            return null;
        }
        if (layout == null) {
            layout = PatternLayout.createDefaultLayout();
        }
        return new TestAppender(name, filter, layout);
    }

    public List<String> getMessages() {
        return messages;
    }

    public void setMessages(List<String> messages) {
        this.messages = messages;
    }    
}

2-将appender添加到log42-test.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" packages="com.example.appender">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
        <TestAppender name="TestAppender" >
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </TestAppender> 
    </Appenders>
    <Loggers>
        <Logger name="com.example" level="All" />
        <Root>
            <AppenderRef ref="Console" level="All" />
            <AppenderRef ref="TestAppender" level="All" /> 
        </Root>
    </Loggers>
</Configuration>

3-在Junit测试中获取对appender的引用。

public class LoggingInterceptorTest {

    @Autowired
    private InterceptedComponent helperComponent;

    private TestAppender appender;

    @Before
    public void setUp() {
        final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        final Configuration config = ctx.getConfiguration();
        appender = (TestAppender) config.getAppenders().get("TestAppender");
    }

    @Test
    public void test_wrapping() {
        helperComponent.doStuff("437");
        Assert.assertEquals(appender.getMessages().size(), 2);
    }
}

在您的测试用例中,您可以检查写入的消息数或包含所需消息的列表。

答案 1 :(得分:3)

我建议您查看log4j2中的JUnit测试。

许多log4j2单元测试使用带有immediateFlush = true的FileAppender,然后读入文件并检查输出中是否存在某些预期的字符串。其他人配置一个(org.apache.logging.log4j.test.appender。)ListAppender(这个类存在于核心测试jar中)并直接从列表中获取LogEvent对象。

您可能需要为log4j2 JUnit测试分叉一个新进程,以确保先前的某个进程尚未加载其他配置。

答案 2 :(得分:0)

一个选项是使用自定义的OutputStreamAppender子类将记录器配置为写入内存中的字符串(字节数组)流,您必须对其进行编码。

然后,您可以在测试中对结果字符串使用断言。

我最近制作了一篇关于做这个here的博客文章。也许它会帮助你。