java - 使用@Slf4j 注释创建时如何模拟 Logger?

标签 java unit-testing mockito slf4j

我有一个带有@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注释将代码注入(inject)您的类 在编译时 .具体来说,它会将以下代码添加到您的类中:

private static final org.slf4j.Logger log =
                        org.slf4j.LoggerFactory.getLogger(LogExample.class);
@InjectMocks告诉 Mockito 创建您的类的实例并注入(inject)模拟作为其依赖项 运行时 .
记录器在编译时注入(inject)。依赖是在运行时注入(inject)的。这就是为什么您的记录器不会被 mock ,也不能像这样被 mock 。如果您查看上面注入(inject)的记录器代码,您就会明白,模拟记录器的唯一方法是模拟 LoggerFactory(Mockito 可以模拟自版本 3.4,IIRC 起的静态方法)并使其返回记录器模拟。
注意:让模拟返回模拟通常是一个坏主意,应该避免。 @Slf4j太方便了不能用。这是一个权衡。
注意:如果您只想让记录器静音,那么您也可以将其配置为在测试中关闭。

关于java - 使用@Slf4j 注释创建时如何模拟 Logger?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66816515/

相关文章:

java - 声明 Java 对象数组

java - 冷启动 : Snapshot doesn't exist

java - Android 上的 GCM 演示客户端,错误为 "Unable to instantiate activity"

php - 代码覆盖率报告错误地指示 Controller 的 100% 覆盖率

java - PowerMock:模拟具有不同参数的同一方法的多次调用表现异常

java - 如何避免 Tomcat 应用程序 .war 文件重新部署时的 DB2 驱动程序类加载器内存泄漏

java - 使用cameltestsupport进行Camel单元测试,模板始终为空

c# - 如何验证使用正确表达式调用的模拟异步方法?

java - 模拟 oracle STRUCT 类以实现 junit 覆盖

java - 如何在 Mockito 中模拟 CompletableFuture 的完成