如何在Spring Boot中使用Mockito verify单元测试@Slf4j日志
解决Mock Logger无法验证日志调用的问题
你直接用@Mock声明Logger却验证失败,核心原因是业务代码里用到的Logger实例和你Mock的根本不是同一个。绝大多数日志框架(比如SLF4J、Log4j2)都是通过静态工厂方法(比如LoggerFactory.getLogger(XXX.class))获取Logger实例,你Mock的这个Logger并没有被业务代码引用到,自然验证不到调用。
下面给你几种可行的解决办法:
1. 让业务代码支持Logger注入(推荐方案)
把Logger改成类的成员变量,通过构造方法或Setter注入,替代直接静态获取的方式,这样测试时就能把Mock的Logger传进去。
业务类示例:
public class YourService { private final Logger logger; // 构造注入,测试时可以直接传入Mock的Logger public YourService(Logger logger) { this.logger = logger; } public void callTestMethod() { logger.error("测试错误日志"); } }
测试类写法:
@Mock private Logger logger; @InjectMocks private YourService yourService; @Test void testLoggedEvent() { yourService.callTestMethod(); verify(logger).error(anyString()); verifyNoMoreInteractions(logger); }
这样Mock的Logger会被@InjectMocks自动注入到业务类中,验证就能正常生效。如果是Spring项目,也可以用@Autowired注入Logger,效果一致。
2. 用PowerMock拦截静态LoggerFactory调用(兼容老项目)
如果不能修改业务代码,就用PowerMock拦截静态工厂方法的调用,让业务类获取到你Mock的Logger实例。
测试类示例:
@RunWith(PowerMockRunner.class) @PrepareForTest(LoggerFactory.class) // 声明要拦截的静态类 public class YourServiceTest { private YourService yourService; @Mock private Logger logger; @Before public void setUp() { PowerMockito.mockStatic(LoggerFactory.class); // 指定当业务类获取自身类的Logger时,返回Mock实例 when(LoggerFactory.getLogger(YourService.class)).thenReturn(logger); yourService = new YourService(); } @Test void testLoggedEvent() { yourService.callTestMethod(); verify(logger).error(anyString()); verifyNoMoreInteractions(logger); } }
这种方式不需要改动业务代码,但要引入PowerMock相关依赖,适合无法重构的老项目。
3. Spy包装真实Logger(临时应急方案)
如果不想改代码也不想引入PowerMock,可以用Mockito Spy包装真实的Logger,再替换到业务类中(前提是Logger是可访问的成员变量):
@Test void testLoggedEvent() { Logger realLogger = LoggerFactory.getLogger(YourService.class); Logger spyLogger = Mockito.spy(realLogger); // 替换业务类里的Logger成员变量(需保证变量可访问,比如public或用反射) yourService.logger = spyLogger; yourService.callTestMethod(); verify(spyLogger).error(anyString()); }
这个方法局限性大,依赖Logger的访问权限,只适合临时验证,不推荐作为长期方案。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

