PowerMock 简介
PowerMock 是一个框架,它以更强大的功能扩展了其他模拟库,如 EasyMock 。PowerMock 使用自定义类加载器和字节码操作来实现对静态方法、构造函数、最终类和方法、私有方法、静态初始化器的删除等的模拟。通过使用自定义类加载器,无需对IDE或持续集成服务器进行任何更改,从而简化了采用。PowerMock 旨在使用少量方法和注释扩展现有API,以启用额外功能。目前 PowerMock 支持 EasyMock 和 Mockito。
本篇主要围绕 Mockito 展开.
Mockito
依赖
<properties>
<powermock.version>2.0.2</powermock.version>
</properties>
<dependencies>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
用法
模拟普通方法
public class NormalMethodClass {
public String hello() {
return "hi";
}
}
@RunWith(PowerMockRunner.class)
public class NormalMethodClassTest {
@Test
public void hello() {
NormalMethodClass normalMethodClass = PowerMockito.mock(NormalMethodClass.class);
PowerMockito.when(normalMethodClass.hello()).thenReturn("world");
Assert.assertEquals(normalMethodClass.hello(), "world");
}
}
模拟静态方法
public final class StaticMethodClass {
public static boolean m1() {
return false;
}
}
@PrepareForTest(StaticMethodClass.class)
@RunWith(PowerMockRunner.class)
public class StaticMethodClassTest {
@Test
public void m1() {
PowerMockito.mockStatic(StaticMethodClass.class);
PowerMockito.when(StaticMethodClass.m1()).thenReturn(true);
assertTrue(StaticMethodClass.m1());
}
}
模拟私有方法
public class PrivateMethodClass {
public String testM1(String a) {
System.out.println("testM1:"+ a);
return m1(a);
}
private String m1(String a) {
System.out.println("m1:"+ a);
return a;
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(PrivateMethodClass.class)
public class PrivateMethodClassTest {
@Test
public void m1() throws Exception {
String param = "a";
PrivateMethodClass privateMethodClass = PowerMockito.spy(new PrivateMethodClass());
PowerMockito.doReturn(param).when(privateMethodClass, "m1", param);
Assert.assertEquals(privateMethodClass.testM1(param), param);
}
}
注入模拟
public class NormalMethodClass {
public String hello() {
return "hi";
}
}
public class InjectMockClass {
private NormalMethodClass normalMethodClass;
public InjectMockClass(NormalMethodClass normalMethodClass) {
this.normalMethodClass = normalMethodClass;
}
public String hello() {
return normalMethodClass.hello();
}
}
@RunWith(PowerMockRunner.class)
public class InjectMockClassTest {
@InjectMocks
private InjectMockClass injectMockClass;
@Mock
private NormalMethodClass normalMethodClass;
@Test
public void hello() {
PowerMockito.when(normalMethodClass.hello()).thenReturn("hi");
Assert.assertEquals("hi", injectMockClass.hello());
}
}
测试私有方式
public class PrivateMethodClass {
public String testM1(String a) {
System.out.println("testM1:"+ a);
return m1(a);
}
private String m1(String a) {
System.out.println("m1:"+ a);
return a;
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(PrivateMethodClass.class)
public class CallPrivateMethodClassTest {
@InjectMocks
private PrivateMethodClass privateMethodClass;
@Test
public void m1() throws Exception {
String param = "a";
Method method = PowerMockito.method(PrivateMethodClass.class, "m1", String.class);
Object res = method.invoke(privateMethodClass, param);
Assert.assertNotNull(res);
Assert.assertEquals(res, param);
}
}
注解
@PrepareForTest
需要使用此批注定义的类通常是那些需要字节码操作的类。这包括最终类,具有最终方法,私有方法,静态方法或本机方法的类,应对其进行模拟,以及应在实例化时返回模拟对象的类。
该注释可以放在测试类和单个测试方法上。如果放在一个类中,则该测试类中的所有测试方法都将由PowerMock处理(以实现可测试性)。要为单个方法覆盖此行为,只需在特定的测试方法上放置
如果使用 junit 4.x,注释应始终与 @RunWith(PowerMockRunner.class) 结合使用
@Mock
将字段标记为模拟。
最小化重复的模拟创建代码。
使测试类更具可读性。
NormalMethodClass normalMethodClass = PowerMockito.mock(NormalMethodClass.class);
等价于
@Mock
NormalMethodClass normalMethodClass;
@InjectMocks
将字段标记为注入
允许 mock 和 spy 注入 Mockito 将尝试通过构造函数注入、setter注入或属性注入 mocks。如果以下任何策略失败,则Mockito不会报告失败; 即您必须自己提供依赖项。
网友评论