PowerMock

说明
本文使用的开发环境为JDK1.8。
本文使用的框架版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

<!-- Mockito 2016.8.8目前1.*为稳定版 2.*为beta -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>

<!-- PowerMock -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.4</version>
<scope>test</scope>
</dependency>

关于PowerMock的版本兼容问题,点击这里查看


简介

PowerMock可以支持EasyMock和Mockito,作为Mockito的扩展,使用PowerMock可以mock private方法,mock static方法,mock final方法,mock construction方法。PowerMock封装了部分Mockito的API,可以使用Mockito的语法来进行测试代码的编写。

Basically, PowerMock provides a class called “PowerMockito” for creating mock/object/class and initiating verification, and expectations, everything else you can still use Mockito to setup and verify expectation (e.g. times(), anyInt()).

All usages require @RunWith(PowerMockRunner.class) and @PrepareForTest annotated at class level.


核心元素

核心的关键词或者关键知识点


地心历险(TODO)

揭示底层的原理


实战

Tips

  • 在使用PowerMock时,必须将@RunWith(PowerMockRunner.class) and @PrepareForTest注解到类级别上

  • 关于Argument Matcher的使用与Mockito中类似,此处不再赘述!

  • 在下面的示例中我们没有使用 ‘import static’,以便大家更好的理解方法属于Mockito还是PowerMockito。但是我们强烈建议你在实际编写测试代码中使用‘import static’,这样的可读性更好!
    官方原文:

In the examples below we don’t use static imports for the method in the Mockito or PowerMockito API for better understanding of where the methods are located. However we strongly encourage you to statically import the methods in your real test cases for improved readability.

个人建议:由于PowerMock封装了Mockito的API,所以同时引入两个框架的static method可能会造成编译器不知道调用哪个方法。因此在使用PowerMock相关的API时,通过‘import static’引入PowerMock相关的static method,而不引入Mockito的static method,通过‘Mockito.staticMthod()’显示调用Mockito的相关API。[tbd]

  • 下面的示例代码只是为了展示PowerMock的用法,其中的测试方法(逻辑)可能并不适用于真实的测试代码编写工作!

1. Static Method

1.1 Mock & Stubbing

分为两个步骤:
1.调用PowerMockito.mockStatic()来mock一个静态类(如果要mock某个特定的方法,可以使用PowerMockito.spy(class));

2.使用Mockito.when()进行stub;

代码示例:

1
2
PowerMockito.mockStatic(Static.class);
Mockito.when(Static.firstStaticMethod(param)).thenReturn(value);

1.2 Verify

检验行为分成两步:
1.首先调用PowerMockito.verifyStatic()开始校验动作

2.然后调用你想要校验的静态方法

代码示例:

1
2
PowerMockito.verifyStatic(); // default times is once
Static.firstStaticMethod(param); // 2

important
每一个静态方法的校验前,都应该调用一次verifyStatic()。
官方原文:

Important: You need to call verifyStatic() per method verification.

1.3 stub void static method to throw exception

代码示例:

1
2
3
4
5
6
// arrange
PowerMockito.doThrow(new NullPointerException()).when(StaticExample.class);
StaticExample.isVoidStaticMethod(); //call the method stubbed to stub

// act, call the method again
StaticExample.isVoidStaticMethod();

使用PowerMockito.doThrow(~).when(~)来stub,并且调用一次你要stub的方法,完成stub!

2. private method

对于私有方法,需要采用局部模拟(partial mocking)的手段来实现!

2.1 mock & stub

先构建spy对象,然后通过PowerMockito.when(underTest, nameOfMethodToMock, …param).thenXXX()来实现;(会在打桩时产生真实调用)
或者采用PowerMockito.doXXX().when(underTest, nameOfMethodToMock, …param)实现;(推荐使用,不会产生任何真实调用)

代码示例:

1
2
3
4
StaticExample staticExampleMock = PowerMockito.spy(new StaticExample());
// For private methods use PowerMockito.when
PowerMockito.doReturn(RETURN_VALUE).when(staticExampleMock,"isPrivateMethod",anyInt());
//when(staticExampleMock,"isPrivateMethod",anyInt()).thenReturn(RETURN_VALUE);

2.2 verify

代码示例:

1
verifyPrivate(staticExampleMock).invoke("isPrivateMethod", anyInt());

3. Constructor

3.1 mock & stub

代码示例:

1
PowerMockito.whenNew(MyClass.class).withNoArguments().thenThrow(new IOException("error message"));

有参数的构造器也有相应的stub,形如whenNew(~).withXXX(~).thenXXX(~),可以参见API,此处不赘述!

Notice:在@PrepareForTest(Class<?>[] value)中,应该写入调用构造器的方法所属对象的类型!
代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
@RunWith(PowerMockRunner.class)
@PrepareForTest(X.class)
public class XTest {
@Test
public void test() {
whenNew(MyClass.class).withNoArguments().thenThrow(new IOException("error message"));

X x = new X();
x.y(); // y is the method doing "new MyClass()"

..
}
}

3.2 verify

代码示例:

1
PowerMockito.verifyNew(MyClass.class).withNoArguments();

4. final method

final method 的mock, stub, verify与普通方法类似,此处不再赘述!


参考资料

鄙人编写的代码示例(部分来自官网示例,适量修改,并添加额外的示例)
PowerMock On Github
使用PowerMock进行Mock测试
PowerMock简介



PowerMock
https://oabern.github.io/posts/201612083509692517/
作者
OABern
发布于
2016年12月8日
许可协议