使 mockito 在单元测试期间使用真正的 Log4j

Making mockito to use the real Log4j during unit testing

在方法 Utility#sum 的单元测试期间,我希望 log 应该打印 sum 在控制台上。

public class Utility {

    private static Logger log = Logger.getLogger(Utility.class);
   
    private Utility() {
    }

    public static Integer getSum(Integer a, Integer b) {
        Integer sum = a + b
        log.info(sum);
        return sum;
    }
}

为此,在我的测试中 testGetSumRealLogger 我正在传递一个真实的 Logger log = Logger.getLogger(getClass()),但在方法 Utility#sum 中,它被初始化为 null。

在我的第二个测试中 testGetSumMockedLogger 我正在传递一个模拟的 Logger log = Mockito.mock(Logger.class) ,这次日志里面的方法Utility#sum不为空,但是不打印任何东西。

class UtilityTest {

    @Test
    void testGetSumRealLogger() throws Exception {
        try (MockedStatic<Logger> mockedStaticLoggerBean = Mockito.mockStatic(Logger.class)) {

            Logger log = Logger.getLogger(getClass());
            mockedStaticLoggerBean.when(() -> Logger.getLogger(Utility.class)).thenReturn(log);

            assertEquals(4, Utility.getSum(2, 2));
        }
    }

    @Test
    void testGetSumMockedLogger() throws Exception {
        try (MockedStatic<Logger> mockedStaticLoggerBean = Mockito.mockStatic(Logger.class)) {

            Logger log = Mockito.mock(Logger.class);
            mockedStaticLoggerBean.when(() -> Logger.getLogger(Utility.class)).thenReturn(log);

            assertEquals(4, Utility.getSum(2, 2));
        }
    }

}

如何在不重构代码的情况下让 Logger 在 Utility#sum 方法中打印某些内容。 我正在使用 Junit 5 和 mockito-inline,3.11.2。 我在测试资源中也有一个适当的 log4j.xml 。 请避免在单元测试期间提示日志记录错误。

首先,在你的情况下不需要模拟:Logger.getLogger 的真正实现做了正确的事情。

因此,代码如下:

@Test
public void testGetSum() {
    assertEquals(4, Utility.getSum(2, 2));
}

工作正常并遵守 log4j 配置的设置。

您通过模拟静态 getLogger 提供记录器的两次尝试都破坏了此功能。

尝试 1:提供真实的记录器

try (MockedStatic<Logger> mockedStaticLoggerBean = Mockito.mockStatic(Logger.class)) {

    Logger log = Logger.getLogger(getClass());
    mockedStaticLoggerBean.when(() -> Logger.getLogger(Utility.class)).thenReturn(log);

    assertEquals(4, Utility.getSum(2, 2));
}

这是错误的,因为当 Logger class 的静态方法已经修补时,您初始化了 log 变量。由于您没有提供 getLogger 的实现,它 returns 任何引用类型的默认值 - null。

尝试 2:提供模拟记录器

try (MockedStatic<Logger> mockedStaticLoggerBean = Mockito.mockStatic(Logger.class)) {

    Logger log = Mockito.mock(Logger.class);
    mockedStaticLoggerBean.when(() -> Logger.getLogger(Utility.class)).thenReturn(log);

    assertEquals(4, Utility.getSum(2, 2));
}

这已损坏,因为您提供的模拟 log 没有指定任何行为 - 它在与之交互时不执行任何操作。