最新消息:

@Log4j2 中的 log 变量到底是从哪里来的,应该如何做单元测试

未分类 niuge678 368浏览 0评论

背景

最近写代码,遇到一个问题。一个函数有许多分支当满足一定条件时,直接退出,并且没有返回值。

if (sStatusChanged)) {
    log.info("no need to calculate for user id : {}", userId);
    return;
}

如果想验证函数在正确的位置退出了,我能想到的方法,一种方法是验证 log.info 函数被正确执行了,另外一种方法是验证下面的逻辑没有执行(比如 userDao.getUser(userId); 没有执行。由于 userDao 往往是 mock 的,比较容易验证有没有执行)。第一种方法是比较准确的。第二种方法由于 userDao.getUser(userId); 可能还有一个判断分支直接退出,不完全准备。

我在使用第一种方法做测试时,遇到了一些困难,做一下记录。

@Log4j2 中的 log 变量到底是从哪里来的

添加 @Log4j2 跟在代码里添加 private static final Logger log = LogManager.getLogger(MyClass.class); 效果其实是一样的,在编译的阶段,@Log4j2 会帮你生成一个 log 变量供你使用。

初始化测试类之前 mock static

这是今天最主要的犯错。

  1. 跟 MockitoAnnotations.openMocks(this) 没关系。
  2. 跟 @ExtendWith(MockitoExtension.class) 也没关系。
  3. 跟 src/main/resource/log4j2.xml 里的内容也没关系。
appConfig.when(() -> LogManager.getLogger(CaseSlaHandle2.class)).thenAnswer(invocation -> {
    System.out.println("LogManager.getLogger called");
    return mockLogger;
});

userSlaHandler2 = new UserSlaHandle2(); 测试类的初始化一定要在 mock static 之后,否则 mock 不起作用。

发现另外一个问题是,由于 log 是静态变量,类一直在使用同一个 log 对象(即使重新 new 之后)。

解决方法是:

  1. 使用 private static Logger logger = mock(Logger.class); ,不使用 @Mock。注意,logger 是静态的,这样 logger 就固定住了。本质原因是,在 JUnit 测试中使用 @Mock 注解来模拟对象时,每次运行测试方法时都会创建一个新的 mock 实例。

  2. 在方法执行之前和执行之后,运行 Mockito.reset(logger);。

转载请注明:牛哥678 » @Log4j2 中的 log 变量到底是从哪里来的,应该如何做单元测试

与本文相关的文章

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址