同一JUnit测试类混用Mockito与PowerMockito时Mock方法报错咨询
我之前也碰到过一模一样的坑!用PowerMock拦截对象实例化再结合Mockito mock方法的时候,很容易因为配置顺序或者注解漏加导致奇怪的报错,给你几个排查和解决的方向:
必须添加@PrepareForTest注解,且目标是被测类
光加@RunWith(PowerMockRunner.class)是不够的,PowerMock需要修改被测类的字节码来拦截new操作,所以一定要给测试类加上@PrepareForTest,指定你要测试的那个包含new对象逻辑的类,而不是被mock的依赖类:@RunWith(PowerMockRunner.class) @PrepareForTest({YourTestedService.class}) // 这里填的是你的被测类,不是被mock的Dependency类 public class YourTestedServiceTest { // 测试代码 }这是最容易踩的坑,很多人会把被mock的类填进去,导致拦截失败。
严格控制mock的顺序
正确的顺序应该是:- 先创建依赖类的mock对象
- 用
PowerMockito.whenNew指定这个mock对象作为new操作的返回值 - 再用Mockito/PowerMockito mock这个mock对象的方法
- 最后执行被测方法
示例代码:
// 1. 创建mock对象 DependencyClass mockDependency = Mockito.mock(DependencyClass.class); // 2. 拦截new操作,返回mock对象 PowerMockito.whenNew(DependencyClass.class).withAnyArguments().thenReturn(mockDependency); // 3. mock mock对象的方法 Mockito.when(mockDependency.method1(1000)).thenReturn(yourCreatedObject); // 4. 执行被测方法 YourTestedService testedService = new YourTestedService(); testedService.yourMethodUnderTest();如果顺序搞反,比如先mock方法再设置whenNew,会导致mock的方法逻辑不生效。
检查方法参数的匹配逻辑
如果你mockmethod1(1000)时,被测方法里实际传入的参数和1000不匹配,就会报错或者返回默认值。可以用Mockito的参数匹配器来灵活匹配:// 匹配任意int类型参数 Mockito.when(mockDependency.method1(Mockito.anyInt())).thenReturn(yourCreatedObject);注意:如果使用了参数匹配器,方法的所有参数都必须用匹配器,不能混合具体值和匹配器。
确认PowerMock和Mockito的版本兼容性
版本不匹配是很多隐性报错的根源,比如PowerMock 2.0.x需要搭配Mockito 2.x,PowerMock 1.7.x对应Mockito 1.x。如果你的版本组合不对,很可能出现mock逻辑不生效或者直接抛出异常的情况。如果依赖方法是final类型,改用PowerMockito.mock
如果method1是final方法,Mockito默认无法mock,这时候需要用PowerMockito来创建mock对象,并且用PowerMockito来mock方法:DependencyClass mockDependency = PowerMockito.mock(DependencyClass.class); PowerMockito.when(mockDependency.method1(1000)).thenReturn(yourCreatedObject);
内容的提问来源于stack exchange,提问作者Sat

