Mockito 允许我们创建模仿对象. 由于静态方法属于类,所以在 Mockito 中没有办法模仿静态方法. 然而,我们可以使用 PowerMock 和 Mockito 框架来模仿静态方法。
Mockito Mock 静态方法使用 PowerMock
PowerMock提供不同的模块来扩展 [Mockito 框架]( / 社区 / 教程 / mockito - 教程)并运行 JUnit 和 TestNG 测试案例. 请注意, PowerMock 尚未支持 [JUnit 5]( / 社区 / 教程 / junit5- 教程),因此我们将创建 JUnit 4 测试案例。
PowerMock 依赖
我们需要遵循PowerMock依赖性来嘲笑Mockito中的静态方法。
powermock-api-mockito2
:这是核心的PowerMock依赖性,用于扩展Mockito2模仿框架。如果您正在使用Mockito 1.x版本,则使用‘powermock-api-mockito’模块powermock-module-junit4
:使用PowerMock运行 JUnit 4测试案例powermock-module-testng
:运行TestNG测试案例并支持PowerMock
下面是我们项目的最终pom.xml。
1<project xmlns="https://maven.apache.org/POM/4.0.0"
2 xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <groupId>com.journaldev.powermock</groupId>
6 <artifactId>PowerMock-Examples</artifactId>
7 <version>0.0.1-SNAPSHOT</version>
8
9 <properties>
10 <testng.version>6.14.3</testng.version>
11 <junit4.version>4.12</junit4.version>
12 <mockito-core.version>2.19.0</mockito-core.version>
13 <powermock.version>2.0.0-beta.5</powermock.version>
14 <java.version>10</java.version>
15 </properties>
16
17 <dependencies>
18 <!-- TestNG -->
19 <dependency>
20 <groupId>org.testng</groupId>
21 <artifactId>testng</artifactId>
22 <version>${testng.version}</version>
23 <scope>test</scope>
24 </dependency>
25 <!-- JUnit 4 -->
26 <dependency>
27 <groupId>junit</groupId>
28 <artifactId>junit</artifactId>
29 <version>${junit4.version}</version>
30 <scope>test</scope>
31 </dependency>
32 <!-- Mockito 2 -->
33 <dependency>
34 <groupId>org.mockito</groupId>
35 <artifactId>mockito-core</artifactId>
36 <version>${mockito-core.version}</version>
37 <scope>test</scope>
38 </dependency>
39 <!-- PowerMock TestNG Module -->
40 <dependency>
41 <groupId>org.powermock</groupId>
42 <artifactId>powermock-module-testng</artifactId>
43 <version>${powermock.version}</version>
44 <scope>test</scope>
45 </dependency>
46 <!-- PowerMock JUnit 4.4+ Module -->
47 <dependency>
48 <groupId>org.powermock</groupId>
49 <artifactId>powermock-module-junit4</artifactId>
50 <version>${powermock.version}</version>
51 <scope>test</scope>
52 </dependency>
53 <!-- PowerMock Mockito2 API -->
54 <dependency>
55 <groupId>org.powermock</groupId>
56 <artifactId>powermock-api-mockito2</artifactId>
57 <version>${powermock.version}</version>
58 <scope>test</scope>
59 </dependency>
60 </dependencies>
61 <build>
62 <plugins>
63 <plugin>
64 <artifactId>maven-compiler-plugin</artifactId>
65 <version>3.7.0</version>
66 <configuration>
67 <source>${java.version}</source>
68 <target>${java.version}</target>
69 </configuration>
70 </plugin>
71 <plugin>
72 <groupId>org.apache.maven.plugins</groupId>
73 <artifactId>maven-surefire-plugin</artifactId>
74 <version>2.22.0</version>
75 <dependencies>
76 <dependency>
77 <groupId>org.apache.maven.surefire</groupId>
78 <artifactId>surefire-junit47</artifactId>
79 <version>2.22.0</version>
80 </dependency>
81 <dependency>
82 <groupId>org.apache.maven.surefire</groupId>
83 <artifactId>surefire-testng</artifactId>
84 <version>2.22.0</version>
85 </dependency>
86 </dependencies>
87 <configuration>
88 <additionalClasspathElements>
89 <additionalClasspathElement>src/test/java/</additionalClasspathElement>
90 </additionalClasspathElements>
91 <!-- TestNG Test Fails when executed from command line with message
92 "Cannot use a threadCount parameter less than 1"
93 Works when threadCount is explicitly specified
94 https://gist.github.com/juherr/6eb3e93e2db33979b7e90b63ddadc888-->
95 <threadCount>5</threadCount>
96 </configuration>
97 </plugin>
98 </plugins>
99 </build>
100</project>
请注意,我正在使用2.0.0-beta.5
版本的PowerMock. 但是,这个版本支持Java 10,它仍然处于测试阶段,所以在复杂情况下可能存在一些问题. 当我尝试使用当前的稳定版本1.7.x
,我收到以下错误。
1java.lang.NoSuchMethodError: org.mockito.internal.handler.MockHandlerFactory.createMockHandler(Lorg/mockito/mock/MockCreationSettings;)Lorg/mockito/internal/InternalMockHandler;
2 at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.createMethodInvocationControl(DefaultMockCreator.java:114)
3 at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.createMock(DefaultMockCreator.java:69)
4 at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.mock(DefaultMockCreator.java:46)
5 at org.powermock.api.mockito.PowerMockito.mockStatic(PowerMockito.java:73)
以下是为此例外打开的 GitHub 问题 - issue1和 issue2。
1package com.journaldev.mockito.staticmethod;
2
3public class Utils {
4
5 public static boolean print(String msg) {
6 System.out.println("Printing "+msg);
7 return true;
8 }
9}
JUnit Mockito PowerMock 示例
我们需要做以下操作来整合 PowerMock 与 Mockito 和 JUnit 4。
- 用
@RunWith(PowerMockRunner.class)
注释的测试类 - 用
@PrepareForTest
注释测试类,并使用 PowerMock. - 使用
PowerMockito.mockStatic()
以使用静态方法进行模仿类 - 使用
PowerMockito.verifyStatic()
以使用 Mockito. 验证模仿方法
以下是使用Mockito和PowerMock在JUnit测试案例中嘲笑静态方法的完整示例。
1package com.journaldev.mockito.staticmethod;
2
3import static org.junit.Assert.assertFalse;
4import static org.junit.Assert.assertTrue;
5import static org.mockito.ArgumentMatchers.anyString;
6import static org.mockito.Mockito.atLeast;
7import static org.mockito.Mockito.when;
8
9import org.junit.Test;
10import org.junit.runner.RunWith;
11import org.powermock.api.mockito.PowerMockito;
12import org.powermock.core.classloader.annotations.PrepareForTest;
13import org.powermock.modules.junit4.PowerMockRunner;
14
15@RunWith(PowerMockRunner.class)
16@PrepareForTest(Utils.class)
17public class JUnit4PowerMockitoStaticTest{
18
19 @Test
20 public void test_static_mock_methods() {
21 PowerMockito.mockStatic(Utils.class);
22 when(Utils.print("Hello")).thenReturn(true);
23 when(Utils.print("Wrong Message")).thenReturn(false);
24
25 assertTrue(Utils.print("Hello"));
26 assertFalse(Utils.print("Wrong Message"));
27
28 PowerMockito.verifyStatic(Utils.class, atLeast(2));
29 Utils.print(anyString());
30 }
31}
Mockito PowerMock 示例
对于 TestNG 测试案例,我们不需要使用@RunWith
注释,我们需要测试类来扩展PowerMockTestCase
,以便使用PowerMockObjectFactory
创建测试类实例。
1package com.journaldev.mockito.staticmethod;
2
3import static org.testng.Assert.assertFalse;
4import static org.testng.Assert.assertTrue;
5
6import static org.mockito.Mockito.*;
7import org.powermock.api.mockito.PowerMockito;
8import org.powermock.core.classloader.annotations.PrepareForTest;
9import org.powermock.modules.testng.PowerMockTestCase;
10import org.testng.annotations.Test;
11
12@PrepareForTest(Utils.class)
13public class TestNGPowerMockitoStaticTest extends PowerMockTestCase{
14
15 @Test
16 public void test_static_mock_methods() {
17 PowerMockito.mockStatic(Utils.class);
18 when(Utils.print("Hello")).thenReturn(true);
19 when(Utils.print("Wrong Message")).thenReturn(false);
20
21 assertTrue(Utils.print("Hello"));
22 assertFalse(Utils.print("Wrong Message"));
23
24 PowerMockito.verifyStatic(Utils.class);
25 Utils.print("Hello");
26 PowerMockito.verifyStatic(Utils.class, times(2));
27 Utils.print(anyString());
28 }
29}
摘要
PowerMock为Mockito提供了扩展的功能,其中之一是测试静态方法的能力,它可以很容易地集成到 JUnit 4 和 TestNG。
您可以从我们的 GitHub 存储库下载完整的项目。