Table of contents
4 PowerMock
JDK 版本方面,8 或者 11 都可以。
4.1 Maven dependencies
因為 PowerMock 同 Mockito 既一啲兼容性問題,我地一定要用 Mockito 3.9.0
,唔可以用 4.0.0
或者以上既版本。
1<properties>
2 <powermock.version>2.0.9</powermock.version>
3</properties>
4
5<dependencyManagement>
6 <dependencies>
7 <dependency>
8 <groupId>org.springframework.boot</groupId>
9 <artifactId>spring-boot-dependencies</artifactId>
10 <version>2.7.1</version>
11 <type>pom</type>
12 <scope>import</scope>
13 </dependency>
14 </dependencies>
15</dependencyManagement>
16
17<dependencies>
18 <dependency>
19 <groupId>org.springframework.boot</groupId>
20 <artifactId>spring-boot-starter-web</artifactId>
21 </dependency>
22
23 <dependency>
24 <groupId>org.apache.commons</groupId>
25 <artifactId>commons-lang3</artifactId>
26 </dependency>
27
28 <dependency>
29 <groupId>org.springframework.boot</groupId>
30 <artifactId>spring-boot-starter-test</artifactId>
31 <scope>test</scope>
32 </dependency>
33
34 <dependency>
35 <groupId>org.junit.vintage</groupId>
36 <artifactId>junit-vintage-engine</artifactId>
37 <scope>test</scope>
38 </dependency>
39
40 <dependency>
41 <groupId>org.powermock</groupId>
42 <artifactId>powermock-module-junit4</artifactId>
43 <version>${powermock.version}</version>
44 <scope>test</scope>
45 </dependency>
46
47 <dependency>
48 <groupId>org.powermock</groupId>
49 <artifactId>powermock-api-mockito2</artifactId>
50 <version>${powermock.version}</version>
51 <scope>test</scope>
52 </dependency>
53
54 <dependency>
55 <groupId>org.powermock</groupId>
56 <artifactId>powermock-module-junit4-rule-agent</artifactId>
57 <version>${powermock.version}</version>
58 <scope>test</scope>
59 </dependency>
60
61 <dependency>
62 <groupId>org.mockito</groupId>
63 <artifactId>mockito-core</artifactId>
64 <version>3.12.4</version> <!--$NO-MVN-MAN-VER$-->
65 <scope>test</scope>
66 </dependency>
67</dependencies>
68
69<build>
70 <plugins>
71 <plugin>
72 <groupId>org.springframework.boot</groupId>
73 <artifactId>spring-boot-maven-plugin</artifactId>
74 <executions>
75 <execution>
76 <goals>
77 <goal>repackage</goal>
78 </goals>
79 </execution>
80 </executions>
81 </plugin>
82
83 <plugin>
84 <groupId>org.apache.maven.plugins</groupId>
85 <artifactId>maven-surefire-plugin</artifactId>
86 <version>3.0.0-M7</version>
87 <configuration>
88 <argLine>-Djdk.attach.allowAttachSelf=true</argLine>
89 </configuration>
90 </plugin>
91 </plugins>
92</build>
註:-Djdk.attach.allowAttachSelf=true
係用黎解決 JDK 8 之後既新版 JDKs 所出現既「Can not attach to current VM」問題。
參考資料:
4.2 寫 Java code
先建立一個典型既 Spring Boot web application。
寫一個 dummy component:
@Component
public class MyComponent {
}
之後我地可以寫 test code:
1@PrepareForTest({ StringUtils.class, RandomStringUtils.class })
2@PowerMockIgnore({ "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*" })
3@SpringBootTest
4@RunWith(SpringRunner.class)
5public class MockStaticSpringTest {
6
7 @Autowired
8 MyComponent myComponent;
9
10 @Rule
11 public PowerMockRule powerMockRule = new PowerMockRule();
12
13 @Before
14 public void setUp() {
15 PowerMockito.spy(StringUtils.class);
16 PowerMockito.mockStatic(RandomStringUtils.class);
17 }
18
19 // Spring Boot test,可以測試 Spring context 能唔能夠成功 load 到
20 @Test
21 public void contextLoads() {
22 assertNotNull(myComponent);
23 }
24
25 @Test
26 public void test_mockStatic_StringUtils() {
27 assertTrue(StringUtils.isBlank(" "));
28 PowerMockito.when(StringUtils.isBlank(any())).thenReturn(false);
29 assertFalse(StringUtils.isBlank(" "));
30 }
31
32 @Test
33 public void test_mockStatic_RandomStringUtils() {
34 assertNull(RandomStringUtils.randomAlphabetic(10));
35 PowerMockito.when(RandomStringUtils.randomAlphabetic(anyInt())).thenReturn("Hello World!");
36 assertEquals("Hello World!", RandomStringUtils.randomAlphabetic(10));
37 }
38}
註:
- 我地用既係
SpringRunner
而唔係 PowerMockRunner
。
- 正因為咁,所以我地要加
@Rule public PowerMockRule powerMockRule = new PowerMockRule();
- 呢個 property 一定要係
public
。
- 呢個 property 要先 initialize,例如
new PowerMockRule()
。
@PowerMockIgnore
有可能需要用到。
- 我地要 mock static 既 class 係 Apache Commons Lang3 既
StringUtils
以及 RandomStringUtils
。
- PowerMock 使用上其實同 Mockito 係非常相似。
PowerMockito.mockStatic(class)
默認會令 mock object 既所有 methods 都冇任何 implementation,即係如果有 return type,佢就會返回 null
或者 false
之類既默認 value,除非我地用 when-then 既寫法賦予被測試既 method 一啲新既 behavior。
PowerMockito.spy(class)
係當我地需要 mock object 默認用返本身既 implementation,除非我地用 when-then 既寫法賦予被測試既 method 一啲新既 behavior。