Java_UT_Mock系列之-06Powermock与Logg
2018-06-25 本文已影响1人
antony已经被占用
简介
日志几乎是所有应用所必备的模块。 在单元测试中,有时候也需要与日志类打交道。笔者用以下案例来介绍如何mock日志类,并完成相关代码行的覆盖。截图为IDE中覆盖率插件的分析结果。
image测试代码
具体测试代码如下:
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import demo.org.powermock.examples.LoggerDemo;
import static org.mockito.Mockito.*;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.*;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(PowerMockRunner.class)
@PrepareForTest({LoggerFactory.class})
public class TestLoggerDemo {
private static Logger loggerMock;
@BeforeClass
public static void setup() {
mockStatic(LoggerFactory.class);
loggerMock = mock(Logger.class);
when(LoggerFactory.getLogger(any(Class.class))).thenReturn(loggerMock);
}
@Test
public void testLoggerInfo() {
//when(loggerMock.isDebugEnabled()).thenReturn(true);
LoggerDemo loggerDemo = new LoggerDemo();
loggerDemo.toInt("100");
//notify here is using atLeastOnce() because that loggerMock is static and all the call will be counted.
verify(loggerMock, atLeastOnce()).info(Mockito.anyString());
}
@Test
public void testLoggerDebugEnabled() {
when(loggerMock.isDebugEnabled()).thenReturn(true);
LoggerDemo loggerDemo = new LoggerDemo();
loggerDemo.toInt("100");
verify(loggerMock, times(1)).debug(Mockito.anyString());
}
@Test
public void testLoggerError() {
//when(loggerMock.isDebugEnabled()).thenReturn(true);
LoggerDemo loggerDemo = new LoggerDemo();
loggerDemo.toInt("出错啦");
verify(loggerMock, times(1)).error(Mockito.anyString());
}
}
有几个问题:
1. 关于是直接修改logger还是 通过LoggerFactory。 本案例采用了后者,技术要点是对于静态方法的Mock。避免了前者去通过反射修改私有final 变量的复杂性。
2. 由于logger是一个静态变量,在不同用例中的所有类似logger.info的方法调用次数都会被记录。本案例中,各测试用例分别会执行logger.info,所以第一个用例中如果采用以下assert会失败,
verify(loggerMock, time(1)).info(Mockito.anyString());
除非控制用例执行顺序。所以采用了现有的模糊匹配方式。