Powermock - 嘲笑org.apache.log4j.Logger?我怎么能够?

fer*_*_dd 4 java unit-testing mockito powermock

我想知道用powermock(和mockito)模拟org.apache.log4j最简单,最简洁的方法是什么.

我尝试了一些方法(我在这里不会说明),但还没有找到实现我想要的方法.我在下面创建了一个简单的类来测试,我想调用run方法并验证是否已经调用了log.info消息.我该怎么做呢?我相信当你知道怎么做时,这很容易!

(我正在使用@Rule,因为我想在弹簧测试下运行,但这应该没有区别).

感谢millon正确的代码.

import org.apache.log4j.Logger;
import org.junit.Rule;
import org.junit.Test;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.rule.PowerMockRule;

public class MockLog4JTest
{
    @Rule
    public PowerMockRule rule = new PowerMockRule();

    private static class ClassUnderTest
    {
        private static Logger logger = Logger.getLogger(ClassUnderTest.class);

        public void run() {
            logger.info("Hello.");
        }

    }

    @Test
    public void testLog()
    {
        ClassUnderTest classUnderTest = new ClassUnderTest();
        classUnderTest.run();
    }

}
Run Code Online (Sandbox Code Playgroud)

Mat*_*man 10

尝试模拟Logger.getLogger()时,Chris和Fildor是正确的.不幸的是,Log4J的工作方式使技术上变得棘手.

以下是我根据您的上述示例提出的(测试过的)代码.

ClassUnderTest.java

import org.apache.log4j.Logger;

public class ClassUnderTest {
    private static Logger logger = Logger.getLogger(ClassUnderTest.class);

    public void run() {
        logger.info("Hello.");
    }
}
Run Code Online (Sandbox Code Playgroud)

MockLog4JTest.java

import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.powermock.api.mockito.PowerMockito.mock;

import org.apache.log4j.Logger;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.rule.PowerMockRule;
import org.powermock.reflect.Whitebox;

@PrepareForTest(ClassUnderTest.class)
public class MockLog4JTest {
    @Rule
    public PowerMockRule rule = new PowerMockRule();

    @BeforeClass
    public static void oneTimeSetup() {
        System.setProperty("log4j.defaultInitOverride", Boolean.toString(true));
        System.setProperty("log4j.ignoreTCL", Boolean.toString(true));
    }

    @Test
    public void testLog()
    {
        ClassUnderTest classUnderTest = new ClassUnderTest();
        Logger mockLogger = mock(Logger.class);

        Whitebox.setInternalState(ClassUnderTest.class, "logger", mockLogger);

        classUnderTest.run();

        verify(mockLogger).info(eq("Hello."));
    }
}
Run Code Online (Sandbox Code Playgroud)

我选择使用Whitebox将被测试类上的静态字段直接设置为我的mockLogger实例.在那之后,验证非常简单.