如何为含Logger的接口默认方法编写Mock测试以覆盖日志逻辑?
如何为含Logger的接口默认方法编写Mock测试以覆盖日志逻辑?
兄弟,你的测试问题核心在于完全绕开了接口的默认方法!你写的匿名内部类自己重写了someMap方法,直接抛出异常,根本没执行到接口默认方法里的catch块和日志逻辑,这就是为什么verify日志时会提示「Wanted but not invoked」。
正确的测试思路
我们要测试的是接口默认方法的catch分支,所以不能重写someMap,而是要让传入的Function在执行时抛出异常,触发默认方法里的错误处理逻辑。
修改后的测试代码
@ExtendWith(MockitoExtension.class) class SomeProcessorTest<T> implements SomeProcessor<T> { @Mock private Logger mockLogger; @Override public void process(Stream<T> someStream) { // 空实现即可,我们不测试这个方法 } // 这里不需要重写someMap,直接用接口的默认方法! @Test void testWithException() { // 使用当前测试类的实例,它会用接口的默认someMap方法 SomeProcessor<String> processor = this; // 构造一个会抛出异常的Function:比如直接抛出测试异常 Function<String, Integer> faultyFunction = str -> { throw new RuntimeException("test exception"); }; String message = "test-message"; // 调用方法,此时会进入默认方法的catch分支 Integer result = processor.someMap(faultyFunction, message, mockLogger); // 验证返回值是null(符合默认方法的逻辑) assertNull(result); // 验证日志是否被正确调用 ArgumentCaptor<Throwable> exceptionCaptor = ArgumentCaptor.forClass(Throwable.class); verify(mockLogger).error( eq("Mapping error for message => {}"), eq(message), exceptionCaptor.capture() ); // 验证捕获的异常类型和信息 assertTrue(exceptionCaptor.getValue() instanceof RuntimeException); assertEquals("test exception", exceptionCaptor.getValue().getMessage()); } }
关键修改点说明
- 不要重写默认方法:测试类实现
SomeProcessor时只重写process,保留someMap的默认实现,这样我们测试的才是接口原本的逻辑。 - 让Function抛出异常:我们要测试的是默认方法的错误处理,所以需要让传入的
Function在执行apply时抛出异常,而不是自己重写someMap抛异常。 - 验证返回值和日志:调用方法后,先验证返回值是否为
null(符合默认方法的逻辑),再验证Logger的error方法是否被正确调用,同时捕获异常参数做断言。
这样修改后,就能覆盖到接口默认方法里的catch块和日志代码了,不会再出现Wanted but not invoked的错误。
备注:内容来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

