PowerMock的使用
引言
上节在使用mock测试时,遇到final、private、static方法,但Mockito不支持这些方法的测试,这时我们需引入PowerMock
导包
想要使用PowerMock,就得先导入其jar包
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<mockito.version>2.8.9</mockito.version>
<powermock.version>1.7.4</powermock.version>
</properties>
<!-- 此处只展示测试的相关依赖 -->
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- powermock 的依赖 -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
如何使用PowerMock测试静态方法
//类上面引入注解,使用PowerMockRunner.class
@RunWith(PowerMockRunner.class)
//使用PrepareForTest注解代替mock注解来模拟静态类
@PrepareForTest({HttpUtils.class})
//排除一些SSL认证异常
@PowerMockIgnore( {"javax.management.*", "javax.net.ssl.*"})
public class PowerMockTest {
@InjectMocks
SynServiceImpl synService;
private static Student student;
@BeforeClass
public static void create() {
student = new Student ();
student.setName("xiaoming");
student.setAge("22");
}
@Before
public void init(){
//PowerMockito.mockStatic(HttpUtils.class);
}
@Test
public void testDoPost() {
String respon = "{" +
"\"result\": \"ok\", " +
"\"req_method\": \"student_synadd\", " +
"\"data\": [{" +
"\"status\": \"ok\"" +
"}], " +
"\"system_time\": \"1556436736.341\"} ";
//设置静态方法的类(使用@before统一设置)
PowerMockito.mockStatic(HttpUtils.class);
//指定需要测试静态方法的行为
PowerMockito.when(HttpUtils.doPost(Mockito.anyString(),Mockito.anyMap())).thenReturn(respon);
synService.addStudent(student);
}
}
其他同mockito,但引入powerMockito后,之前的测试类出现了一点奇葩问题
遇到的问题:
org.mockito.exceptions.misusing.UnnecessaryStubbingException:
Unnecessary stubbings detected in test class: Test
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
- -> at service.Test.testDoSearch(Test.java:72)
Please remove unnecessary stubbings or use ‘silent’ option. More info: javadoc for UnnecessaryStubbingException class.
业务表现:单个方法测试正常,一个类运行测试出现UnnecessaryStubbingException,说是存在未使用的存根,为了代码整洁请去掉这些存根或是使用silent策略。
若注释掉这些未使用的存根,单个方法运行会出现空指针异常,也就是说一个方法里有多个分支,进去这些分支,需要模拟不同的临界值,在整体运行时可能跳过某些细节、忽略掉某些分支,导致出现存根未使用的情况。
解决方法:
-
silent策略
用 @RunWith(MockitoJUnitRunner.Silent.class) 替换@RunWith(MockitoJUnitRunner.class)。
自Mockito 2.1.0起新增功能,将检测测试代码中未使用的存根,来保持代码的清洁,通过注解关闭此功能,但是 不生效,最终发现是jar包版本有冲突导致的,但是不推荐使用这个方法,这只是隐藏问题并没有解决问题。 -
分支独立
将每个分支独立一个测试方法,这样代码有点臃肿,但是在单个运行时没问题,整体运行时有空指针异常,通过debug调试,发现部分值在测试时发现了改变,因此可在提示的空指针处再次进行赋值即可避免此问题。
未完待续。。。。。。。。。。