JUnit:测试没有记录错误

时间:2015-08-21 06:35:10

标签: java unit-testing junit

我正在尝试测试这样的东西:

try {
     logger.info("message");
     //do something
} catch(Exception e) {
     logger.error(errorMessage);
}

我知道捕获异常并不是一个好习惯,但是有一些遗留代码,没有时间进行重构。

所以,我编写了一个单元测试,以便在try块中抛出NullPointerException,但现在我不知道如何编写断言行(显然,单元测试必须一直失败)。 请注意我不能使用:

        final Logger logger = LogManager.getLogger(AnaliticsService.class);
        final Appender mockAppender = mock(Appender.class);
        logger.addAppender(mockAppender);
        final ArgumentCaptor<LoggingEvent> captor = ArgumentCaptor.forClass(LoggingEvent.class);
        Log4jConfigHelper.getInstance().bufferConfiguration();
        verify(mockAppender, times(x)).doAppend(captor.capture());

因为我不知道UT正在运行时会记录多少条消息。

3 个答案:

答案 0 :(得分:0)

  

我编写了一个单元测试,以便在try块中抛出NullPointerException,但现在我不知道如何编写断言行(显然,单元测试必须一直失败)。

您不需要以这种方式检查异常。抛出异常的测试失败。

} catch(Exception e) {
     logger.error(errorMessage, e);
     throw e; // report the error to the test
}

注意:何时向测试框架抛出错误,它会记录/打印它,所以我怀疑你不需要首先捕获它。

答案 1 :(得分:0)

你应该尝试为LoggerFactory做一个模拟。

首先使用:

注释您的TestClass
@RunWith(PowerMockRunner.class)
@PrepareForTest({YourController.class, LoggerFactory.class})

然后进行测试,调用所需的方法并解决错误:

@Test
public void testErrorLogging() throws Exception {
    mockStatic(LoggerFactory.class);

    Logger logger = mock(Logger.class);
    when(LoggerFactory.getLogger(any(Class.class))).thenReturn(logger);

    YourController controller = new YourController();
    controller.someMethod();

    verify(logger).error(anyString());
}

答案 2 :(得分:0)

日志消息是代码用户界面的一部分。执行计算的代码不应该假设日志消息可供用户使用的方式,日志消息的文本和语言,甚至消息是否以文本形式传递(而不是以图形方式传递)。因此,计算代码应委托给隐藏所有这些细节的相关记录器类(在UI /表示层中)。

如果计算代码仅要求关联的记录器符合接口,并使用依赖注入与记录器类关联,则很容易模拟记录器以检查计算代码是否已请求记录。

因此,如果要测试的代码是这样的::

 public class MyService
 {
    private final MyServiceLogger logger;

    MyService(MyServiceLogger logger)
    {
       this.logger = Objects.requireNonNull(logger);
    }

    public void processFile(Path path) {
       ...
       try{
          ...
       } catch (EOFException e) {
          logger.logUnexpectedEOF(path);
       }
    }
 }

 public interface MyServiceLogger
 {
    public logUnexpectedEOF(Path path);
 }

 public class MyServiceTextLogger implements MyServiceLogger
 {
    private final Logger textLogger = LogManager.getLogger(MyService.class);;

    @Override
    public logUnexpectedEOF(Path path) {
       textLogger.error("unexpected EOF for file {}",path);
    }
 }

你可以这样测试:

 public class MyServiceTest
 {
    private static class MockMyServiceLogger implements MyServiceLogger
    {
       private Path path;
       private int nCalls_logUnexpectedEOF;

       @Override
       public logUnexpectedEOF(Path path) {
          ++nCalls_logUnexpectedEOF;
          this.path = path;
       }

       void assertCalled_logUnexpectedEOF(int nCalls, Path path) {
          assertEquals("Called logUnexpectedEOF, nCalls", nCalls, nCalls_logUnexpectedEOF);
          assertEquals("Called logUnexpectedEOF, path", path, this.path);
       }
    }

    @Test
    public void processFile_unexpectedEOF() {
       Path testPath = ...
       ...
       MockMyServiceLogger mockLogger = new MockMyServiceLogger();
       MyService service = new MyService(mockLogger);

       service.processFile(testPath);

       mockLogger.assertCalled_logUnexpectedEOF(1, testPath);
    }

    @Test
    public void processFile_OK() {
       Path testPath = ...
       ...
       MockMyServiceLogger mockLogger = new MockMyServiceLogger();
       MyService service = new MyService(mockLogger);

       service.processFile(testPath);

       mockLogger.assertCalled_logUnexpectedEOF(0, null);
    }
 }