简介 可用于本地单元测试的框架。可模拟公有,私有方法返回数据;也可模拟静态属性数据,实例属性数据;模拟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