简介
可用于本地单元测试的框架。可模拟公有,私有方法返回数据;也可模拟静态属性数据,实例属性数据;模拟Spring Bean 实例及注入等。
与Mockito的区别
PowerMock较Mockito强大一点,可以模拟私有方法,静态方法,final 类。
maven依赖
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <scope>test</scope> </dependency>
|
说明
@Mock 和 @Spy 区别
@Mock:模拟出来的对象,其所有方法是空的,调用都返回空,真实的方法不会执行。
@Spy:模拟出来的对象,其所有方法都是真实的,调用都按真实方法去调用,因此很可能依赖真实的环境。除非mock 对应的方法,才会覆盖。
doReturn()…when() 和when()…thenReturn() 的区别
mock 出来的对象: 没有区别。
spy出来的对象:doReturn()…when() 和when()…thenReturn() 是有区别的
使用
模拟公有方法
- 设置Runner环境为
PowerMockRunner
1 2 3 4 5 6
|
@RunWith(PowerMockRunner.class) public class FoodMenuServiceTest{ }
|
- 定义Mock属性和需要注入的属性。
1 2 3 4 5 6 7 8 9 10 11
|
@InjectMocks private FoodMenuService foodMenuService = new FoodMenuServiceImpl();
@Mock private MaterialService materialService;
|
- 构造数据,模拟方法,运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
@Test public void mockPublicMethod() {
Material fish = Material.builder().name("鱼").build(); Material crayFish = Material.builder().name("小龙虾").build(); ArrayList<Material> materials = CollUtil.newArrayList(fish, crayFish);
PowerMockito.when(materialService.list()).thenReturn(materials);
List<Food> list = foodMenuService.list();
System.out.println(list); }
|
模拟私有方法
- 设置runner环境为PowerMockRunner,并设置PrepareForTest为需要测试的类PrepareForTest
1 2 3 4 5 6
| @RunWith(PowerMockRunner.class) @PrepareForTest(MaterialServiceImpl.class) public class MockPrivateMethodTest { }
|
- 定义需要Spy的属性
1 2 3
| @Spy private MaterialService materialService = new MaterialServiceImpl();
|
- 构造数据,模拟方法,运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Test public void mockPrivateMethod() throws Exception {
Material fish = Material.builder().name("鱼").build(); Material crayFish = Material.builder().name("小龙虾").build(); ArrayList<Material> materials = CollUtil.newArrayList(fish, crayFish);
PowerMockito.doReturn(materials).when(materialService, "pri"); List<Material> list = materialService.listForPri();
System.out.println(list);
}
|
同时模拟共有和私有方法,并注入
- 设置Runner和PrepareForTest
1 2 3 4 5 6
| @RunWith(PowerMockRunner.class) @PrepareForTest(MaterialServiceImpl.class) public class MockPublicAndPrivateMethodTest { }
|
- 定义属性
1 2 3 4 5 6
| @InjectMocks private FoodMenuService foodMenuService = new FoodMenuServiceImpl();
@Spy private MaterialService materialService = new MaterialServiceImpl();
|
- 构造数据,模拟方法,运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Test public void mockPublicAndPrivateMethod() throws Exception {
Material fish = Material.builder().name("鱼").build(); Material crayFish = Material.builder().name("小龙虾").build(); ArrayList<Material> materialsA = CollUtil.newArrayList(fish); ArrayList<Material> materialsB = CollUtil.newArrayList(crayFish);
PowerMockito.doReturn(materialsA).when(materialService, "list");
PowerMockito.doReturn(materialsB).when(materialService, "pri");
List<Food> list = foodMenuService.listForPubAndPri();
System.out.println(list);
}
|
模拟静态方法
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
| import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class) @PrepareForTest(StaticMethodAndField.class) public class StaticMethodAndFieldTest {
public static final String expect = "127.0.0.1";
@Test public void mockStaticMethod() {
PowerMockito.mockStatic(StaticMethodAndField.class); PowerMockito.when(StaticMethodAndField.getIp()).thenReturn(expect);
String ip = StaticMethodAndField.getIp();
Assert.assertEquals(expect, ip);
} }
|
模拟静态私有属性
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 30 31 32 33 34 35 36 37 38 39 40
| @RunWith(PowerMockRunner.class) @PrepareForTest(StaticMethodAndField.class) public class StaticMethodAndFieldTest {
public static final String expect = "127.0.0.1";
@Test public void mockFinalField() throws NoSuchFieldException, IllegalAccessException {
Field field = Whitebox.getField(StaticMethodAndField.class, "IP");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, expect);
Assert.assertEquals(expect, StaticMethodAndField.IP); } }
|
模拟枚举类
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 30 31 32
| import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.Whitebox;
import static org.junit.Assert.*;
@RunWith(PowerMockRunner.class) @PrepareForTest(Colors.class) public class ColorsTest {
@Test public void mockEnums() { String expect = "模拟的蓝色";
Colors instance = PowerMockito.mock(Colors.class);
Whitebox.setInternalState(Colors.class, "BLUE", instance);
PowerMockito.when(instance.getName() ).thenReturn(expect);
assertEquals(expect, Colors.BLUE.getName()); } }
|
项目源码
1
| https://github.com/iaoongin/summary-project/sp-powermock
|