1、引入的包
powermock-module-junit4
powermock-api-mockito2
javassist
mockito-core
2、常用的方法
2.1 方法名上注解
@RunWith(PowerMockRunner.class)
@PrepareForTest(Log.class)
// @PowerMockIgnore({"javax.management.*", "javax.script.*"}) 不要忽略报错
@SuppressStaticInitializationFor({
// 应该抑制 mock的对象静态属性和静态块的初始化
"com.sleepycat.je.SecondaryDatabase"})
2.2 mock类
PowerMockito.mockStatic(Log.class);
// mockstaic 静态类的方法 如果你doNothing 就不需要mock,默认就是 doNothing
// PowerMockito.doNothing().when(Log.class, PowerMockito.method(Log.class, "e", Exception.class)).withArguments(Mockito.any());
// 被测试类 正常属性值,可以直接set
queryPropertiesconfig = PowerMockito.mock(QueryPropertiesconfig.class);
testOwner.queryPropertiesQconfig = queryPropertiesQconfig;
2.3 mock 私有属性 https://blog.csdn.net/github_32521685/article/details/50556243
// BrandSetParam mock实例
MemberModifier.field(BrandSetParam.class, "brandSet").set(param, brandSet);
其他的 mock 静态私有 属性方法
PowerMockito.mockStatic(QueryUtils.class);
// Whitebox.setInternalState(QueryUtils.class, "brandsetcount", 10);
Field field = PowerMockito.field(QueryUtils.class, "brandsetcount");
field.setInt(null ,10);
2.4 模拟私有方法(private method)
MemberModifier.stub(MemberMatcher.method(PrivateObject .class, "getPrivateString")).toReturn( "Power Mock");
抑制父类的方法 和 替换父类的方法
作者:zyxing
链接:https://www.zhihu.com/question/58768289/answer/522121438
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
@RunWith(PowerMockRunner.class)
@PrepareForTest(Bar.class)
public class FooTest {
@Test
public void testBar() throws Exception {
Method method = PowerMockito.method(Bar.class, "bar");
// 抑制父类的这个方法执行
PowerMockito.suppress(method);
Foo foo = new Foo();
foo.bar();
}
@Test
public void testNumBar() throws Exception {
Method methodFoo = PowerMockito.method(Foo.class, "numBar");
// 替换掉父类的方法
PowerMockito.replace(methodFoo).with(new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return 1;
}
});
Foo foo = new Foo();
int numBar = foo.numBar();
Assert.assertEquals(1, numBar);
}
}
2.5 测试被测对象的私有方法,使用反射
Method method = PowerMockito.method(TrafficInfoWrapperImpl.class, "getTrafficInfoEntity", HotelInfoType.class, TrafficInfoParameter.class);
TrafficInfoEntity positionInfo = (TrafficInfoEntity) method.invoke(trafficInfoWrappers, hotelInfoType, trafficInfoParameter);
2.6
3、遇见的异常
java.lang.IllegalStateException: Failed to transform class with name XXXXXX
InterfaceMethodrefInfo cannot be cast to MethodrefInfo
解决办法:
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>javassist</artifactId>
<groupId>org.javassist</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.22.0-GA</version>
</dependency>
参考 : http://www.javaear.com/question/31189086.html
3.2 Mock在前,new 被测试的类的实例 放在后后面,否则可能出现 new 的时候就依赖了 mock的数据,比如有 静态代码块
3.3 mock 任意值 和 特定值 混搭
// 被 mock方法
public static Integer getDefaultInt(String key,Integer defaultValue) {
//}
// correct
PowerMockito.when(SystemInfo.getDefaultInt(Mockito.anyString(), Mockito.anyInt())).thenReturn(3);
// correct
PowerMockito.when(SystemInfo.getDefaultInt("sort.change.day", 2)).thenReturn(3);
// incorrect 不能任意值 和 特定值 混搭
PowerMockito.when(SystemInfo.getDefaultInt(Mockito.anyString(), 2)).thenReturn(3);
对应的报错信息
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
-> at com.ctrip.hotel.search.das.mlstoreproduct.datafilter.MlstoreproductDataFilterTest.testParseDasEntity(MlstoreproductDataFilterTest.java:57)
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
4、InjectMocks 和 Mock
@InjectMocks:创建一个实例,简单的说是这个Mock可以调用真实代码的方法,其余用@Mock(或@Spy)注解创建的mock将被注入到用该实例中。
@Mock:对函数的调用均执行mock(即虚假函数),不执行真正部分。
@Spy:对函数的调用均执行真正部分。
Mockito中的Mock和Spy都可用于拦截那些尚未实现或不期望被真实调用的对象和方法,并为其设置自定义行为。二者的区别在于Mock不真实调用,Spy会真实调用。
@InjectMocks
private HotFeatureRepositoryImpl repository;
@Mock
private GetProvinceFilterClient<List<HotSearchKeywordStatModel>> getProvinceFilterClient;
@Test
public void getHotFeaturesByProvinceAsync_Invalid() {
repository.getHotFeaturesByProvinceAsync(0);
}
注意事项:
InjectMocks 被测试类如果有父类,并且会有一些静态属性初始化的话,会在@before前执行,所以可能会出现NPE等错误。