单元测试第七篇,在第六篇中,介绍了mockito对public方法的mock,但是mockito不支持私有方法、静态方法等,因此,本文介绍PowerMockito库,它在mokito上进行增强,可以mock 静态方法、私有方法、final方法、enum、构造函数等等。
- 注:要使用PowerMockito,必须使用org.junit.Test,且class和method都必须是public
- 参考:https://github.com/powermock/powermock/issues/1030。
- 相关代码已经放在Github上:源代码
特别说明:
在很多地方,都强烈建议不使用该框架,大意就是如果需要对静态方法、私有方法、构造函数等进行mock,说明你的应用架构设计不合理,应该考虑重新设计你的业务实现。
下面简述开发过程:
1、首先,还是正常建立项目,并完成一些常规的业务逻辑开发;
2、项目添加mockito库的引用,打开pom.xml,添加:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.5.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.7</version>
<scope>test</scope>
</dependency>
注1:引用的库,包含第六篇里的mockito。
3、application.yml配置文件无需修改.
4、静态方法mock:
String name = "王霸";
Assert.isTrue(BusinessService.getHello1(name).equals("Hello1, 王霸"), "原生有问题?");
PowerMockito.mockStatic(BusinessService.class);
PowerMockito.when(BusinessService.getHello1(ArgumentMatchers.any())).thenReturn("你好");
Assert.isTrue(BusinessService.getHello1("").equals("你好"), "mock有问题?");
5、构造函数mock:
BusinessService mockObj = PowerMockito.mock(BusinessService.class);
PowerMockito.when(mockObj.requestSinaHtml()).thenReturn("Mock新浪");
// 如果创建 BusinessService对象时,传递了参数 abc,则返回mock对象
PowerMockito.whenNew(BusinessService.class).withArguments("abc").thenReturn(mockObj);
// 创建对象,不符合mock条件,创建会失败
BusinessService noMock = new BusinessService("abcd");
Assert.isTrue(noMock == null, "原生方法?");
// 创建对象,符合mock条件
BusinessService withMock = new BusinessService("abc");
Assert.isTrue(withMock.requestSinaHtml().equals("Mock新浪"), "Mock方法?");
6、私有方法mock:
BusinessService mockObj = PowerMockito.spy(new BusinessService());
// 没mock前,调用原生方法
String tmp = mockObj.getHello2("ab");
Assert.isTrue(tmp.equals("Hello2, ab"), "原生有问题?");
// mock私有方法
PowerMockito.when(mockObj, "getHelloPrivate", Mockito.anyString()).thenReturn("abc");
tmp = mockObj.getHello2("ab");
Assert.isTrue(tmp.equals("abc"), "mock有问题?");
7、final方法mock:
BusinessService mockObj = PowerMockito.spy(new BusinessService());
// 没mock前,调用原生方法
String tmp = mockObj.getHelloFinal("ab");
Assert.isTrue(tmp.equals("Hello, Final ab"), "原生有问题?");
// mock final方法
PowerMockito.when(mockObj.getHelloFinal(Mockito.anyString())).thenReturn("abc");
tmp = mockObj.getHelloFinal("ab");
Assert.isTrue(tmp.equals("abc"), "mock有问题?");
8、enum枚举mock:
BusinessService.EnumDemo mockObj = PowerMockito.mock(BusinessService.EnumDemo.class);
// 没mock前,调用原生方法
String tmp = BusinessService.EnumDemo.enum2.getTitle();
Assert.isTrue(tmp.equals("ENUM2"), "原生有问题?");
// mock enum2 方法
Whitebox.setInternalState(BusinessService.EnumDemo.class, "enum2", mockObj);
PowerMockito.when(mockObj.getTitle()).thenReturn("abc");
// 返回mock后的值
tmp = BusinessService.EnumDemo.enum2.getTitle();
Assert.isTrue(tmp.equals("abc"), "mock有问题?");
// 未mock
tmp = BusinessService.EnumDemo.enum3.getTitle();
Assert.isTrue(tmp.equals("ENUM3"), "mock有问题?");
注:以上代码,在提供的源码Demo里都有。
如果你在运行时有问题,可以下载上面的源码,进行对比,看看你的代码哪里有问题。