我有一个带有 @Slf4j 注释的类。
我尝试编写一个测试并模拟 Logger,但它不起作用。
@RequiredArgsConstructor
@Slf4j
public abstract class ExampleClass {
protected final PropsClass properties;
protected void logInfo(..) {
log.info(...);
clearMappedDiagnosticContext();
}
}
这就是测试的样子:
@RunWith(MockitoJUnitRunner.class)
public class ExampleClassTest {
@Mock
Logger logger;
@Mock
PropsClass properties;
@InjectMocks
ExampleClass exampleClass;
@Test
public void logSomethingtest() {
...
exampleClass.logInfo(...);
Mockito.verify(logger).info(marker, "foo bar {}", ...);
}
这是我得到的错误:
Wanted but not invoked:
logger.info(
MY_MARKER,
"..........",
"....",
"....",
0L
);
Actually, there were zero interactions with this mock.
问题是,如何模拟Logger?
lombok
@Slf4j
注释将代码注入到您的类中在编译时。具体来说,它会将以下代码添加到您的类中:
private static final org.slf4j.Logger log =
org.slf4j.LoggerFactory.getLogger(LogExample.class);
@InjectMocks
告诉 Mockito 创建类的实例并在运行时注入模拟作为其依赖项。
记录器在编译时注入。依赖项是在运行时注入的。这就是为什么你的记录器没有被嘲笑,也不能像这样被嘲笑。如果您查看上面注入的记录器代码,您就会明白,模拟记录器的唯一方法是模拟 LoggerFactory(Mockito 从 3.4 版本开始可以模拟静态方法,IIRC)并使其返回记录器模拟。注意:让模拟返回模拟通常是一个坏主意,应该避免。
@Slf4j
太方便了,不敢用。这是一个权衡。注意:如果您希望它使记录器静音,那么您也可以将其配置为在测试中关闭。
@Test
void logmessageInCaseOfPositiveValidationIsWritten() {
Logger mockedLogger = Mockito.mock(Logger.class);
try (MockedStatic<LoggerFactory> context = Mockito.mockStatic(LoggerFactory.class)) {
context.when(() -> LoggerFactory.getLogger(Mockito.any(Class.class)))
.thenReturn(mockedLogger);
// Your test code and your assertions
Mockito.verify(mockedLogger)
.debug("I am the expected message with param {}",
"paramvalue");
}
}
不要忘记使用下面的上下文创建所需的文件test/resources/mockito-extensions/org.mockito.plugins.MockMaker
以启用静态模拟:
mock-maker-inline
为 Mockito 4.5.1 版本编写。