单元测试mockito mock静态方法

3,772 阅读3分钟

开发工具: IDEA
语言 java 转载

背景

Mockito无法实现对静态函数、构造函数、私有函数、Final 等函数的模拟。 使用powermock进行可以模拟静态方法,删除静态初始化程序,允许模拟而不依赖注入等等

原理:

Mockito使用继承的方式实现mock的,用CGLIB生成mock对象代替真实的对象进行执行,为了mock实例的方法,可以在subclass中覆盖它,而static方法是不能被子类覆盖的,所以Mockito不能mock静态方法。 PowerMock通过在执行测试时在运行时修改字节代码来完成这些技巧。

步骤

第一步:maven依赖

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.6.6</version>
    <scope>compile</scope>
</dependency>

第二步 测试类代码

class 文件前面必须加入 @RunWith和@PrepareForTest

@RunWith(PowerMockRunner.class)
@PrepareForTest({JwtUtils.class})
public class AbnormalDataServiceImplTest {}

如果想要对某个类的静态方法进行mock,则必须在PrepareForTest后面加上相应的类名 在对该类的某个方法进行mock之前,还必须先对整个类进行mock:

@Before
public void setUp() throws Exception {
PowerMockito.mockStatic(JwtUtils.class);
}

在测试方法中,我们对静态的方法进行了mock:

PowerMockito.when(JwtUtils.getCurrentOrgId()).thenReturn(1l);

测试成功

问题

1、# springboot2.x 单元测试 mockito powermock 兼容性问题

在使用springboot做单元测试的时候,发现依赖的mockito已经是2.x了,然后powermock虽然对应有一个api,但是并不能真正的支持,遇到了一系列的兼容问题,最后解决的版本如下

image.png

问题解决方法参考与: blog.csdn.net/u013076044/…

2、PowerMockito.when()参数问题

image.png 在使用 PowerMockito.when()的时候,参数必须都是mock的, 例如在JsonUtils.toListCommonResponse(body, TeamDTO.class);这句中,

public static <T> CommonResponse<List<T>> toListCommonResponse(String json, Class<T> clazz)

toListCommonResponse需要的是一个string类型和class类型的参数进行mock

单纯使用PowerMockito.when(JsonUtils.toListCommonResponse(any(), any(TeamDTO.class))).thenReturn(listCommonResponse);这句会报错

需要把TeamDTO.class->Class.class PowerMokito才会编译通过

3、PowerMockito @value

image.png

在Test中

image.png

image.png

举例:

image.png

PowerMock基本用法

(1) 普通Mock:Mock参数传递的对象

image.png  说明:普通Mock不需要加@RunWith和@PrepareForTest注解。

(2)  Mock方法内部new出来的对象

image.png

说明:当使用PowerMockito.whenNew方法时,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是需要mock的new对象代码所在的类。

(3) Mock普通对象的final方法

image.png

说明: 当需要mock final方法的时候,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是final方法所在的类。 

(4) Mock普通类的静态方法

image.png

说明:当需要mock静态方法的时候,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是静态方法所在的类。

(5) Mock私有方法

image.png

说明:和Mock普通方法一样,只是需要加注解@PrepareForTest(ClassUnderTest.class),注解里写的类是私有方法所在的类。 

(6) Mock系统类的静态和final方法

image.png

说明:和Mock普通对象的静态方法、final方法一样,只不过注解@PrepareForTest里写的类不一样 ,注解里写的类是需要调用系统方法所在的类。

 (7) Mock protected方法

image.png 说明:Mock受保护(protected)的方法时,注解@PrepareForTest里写的类是该方法所在的类,如果存在子类继承父类的该方法时,则@PrepareForTest里写的是子类信息。