如何在日志上单元测试消息?

时间:2017-12-12 11:58:29

标签: java unit-testing logging junit

我有一些正在测试的代码,它调用Java记录器来报告其状态。在JUnit测试代码中,我想确认在此记录器中进行了正确的日志条目。例如;我有2个错误日志用于两个不同的条件。

methodGoingToBeTested(bool a, bool b){
    if(a)
        logger.info("a happened")
    else()
        logger.info("b happened")

}

@Test tester(){

    methodGoingToBeTested(true);
    assertXXXXXX(loggedLevel(),Level.INFO);
}

我想测试看看Logger错误我对实际方法的影响是否准确生成了它要生成的条件。我在网上查了一下,但建议很老了。有没有人有什么建议?感谢您的帮助。

我知道这里有类似的帖子,但该帖子确实已过时,现在无法使用相同的流程来解决这个问题,这就是为什么我首先要问这个问题。

1 个答案:

答案 0 :(得分:1)

您无法对此进行测试的原因可能是因为您在正在测试的类中实例化了记录器。

class MyClass
{
    private final Logger logger = /* whatever */;
}

相反,如果您使用dependency injection,则可以让自己测试此行为。

class MyClass
{
    private final Logger logger;

    MyClass(final Logger logger)
    {
        this.logger = logger;
    }
}

现在,在您的测试中,您注入了模拟或伪造的记录器。以下是使用Mockito的简单示例:

@Mock
Logger logger;

@Test
void tester()
{
    MyClass inst = new MyClass(logger);

    methodUnderTest(true);

    BDDMockito.verify(logger).info(Mockito.anyString());
}

如果您愿意,可以执行更严格的验证。

同样,您可以为测试目的创建一个假的Logger实现,它执行所需的断言,而不是模拟。这是一个非常基本的例子:

class FakeLogger implements Logger
{
    private boolean hasInfoBeenCalled = false;

    @Override
    public void info(String message)
    {
        hasInfoBeenCalled = true;
    }

    // Other Logger methods...

    public boolean hasInfoBeenCalled()
    {
        return hasInfoBeenCalled;
    }
}

@Test
void tester()
{
    FakeLogger logger = new FakeLogger();
    MyClass inst = new MyClass(logger);

    methodUnderTest(true);

    Assert.assertTrue(logger.hasInfoBeenCalled());
}

所有这一切,如果唯一可观察和可测试的行为是写入日志文件,我会仔细重新考虑您的类的设计。如果您决定将来更改日志记录,您可能会发现您的测试非常脆弱。