JUnit中ListAppender无法捕获Logger输出的原因排查
ListAppender无法捕获Logger输出的原因及解决方法
问题背景
需要为以下post方法编写单元测试,验证当restClient.postForObject抛出异常时,Logger会记录ERROR日志:
业务方法代码:
public void post(LexileResults lexileResults) { try { restClient.postForObject(saveEndpoint, lexileResults, LexileResults.class); } catch (Exception e) { logger.error(String.format("Exception thrown for post: {0}", e.getMessage())); } }
类中Logger定义:
final Logger logger = LoggerFactory.getLogger(getClass());
编写的测试代码运行后断言失败,且logsList.get(0)抛出IndexOutOfBoundsException,说明ListAppender未捕获到日志输出。
原因分析
1. Logger实例不匹配
业务类中用LoggerFactory.getLogger(getClass())获取Logger,若测试中的instance是ForecastingService的子类(比如Mockito生成的代理类),getClass()返回的是子类类型,而测试代码中直接用LoggerFactory.getLogger(ForecastingService.class)获取的是父类Logger实例,导致ListAppender被添加到了错误的Logger上,自然捕获不到目标日志。
2. 日志内容断言方式错误
listAppender.list中存储的是ILoggingEvent对象,而非字符串。直接调用contains("Exception thrown for post")会判断列表中是否存在该字符串对象,显然不会匹配,导致断言失败;如果没有日志输出,列表为空,调用get(0)就会触发越界异常。
3. 日志级别配置问题
如果测试环境中Logger的级别被设置为高于ERROR(比如WARN或INFO),那么logger.error()输出的日志会被过滤,ListAppender也无法捕获到。
修正后的测试代码
@Test public void testServicePostWithException() { // 获取与业务实例匹配的Logger Logger logger = (Logger) LoggerFactory.getLogger(instance.getClass()); // 创建并启动ListAppender ListAppender<ILoggingEvent> listAppender = new ListAppender<>(); listAppender.start(); logger.addAppender(listAppender); // 模拟异常场景 LexileResults result = mock(LexileResults.class); RestClientException exception = new RestClientException("something went wrong"); when(restClient.postForObject(Mockito.any(), Mockito.any(), Mockito.any())).thenThrow(exception); // 调用目标方法 instance.post(result); // 正确断言日志内容 List<ILoggingEvent> logsList = listAppender.list; boolean errorLogExists = logsList.stream() .anyMatch(event -> event.getMessage().contains("Exception thrown for post")); assertTrue(errorLogExists); // 清理资源 listAppender.stop(); logger.detachAppender(listAppender); }
额外注意事项
- 若使用SLF4J + Logback,确保测试配置文件(如
logback-test.xml)中Logger的级别设置为ERROR或更低,避免日志被过滤。 - 如果使用Mockito spy创建
instance,可通过反射获取业务类中的logger字段,彻底避免实例类型不匹配的问题。
内容的提问来源于stack exchange,提问作者sFishman
相关产品推荐
相关产品推荐

