PowerMockito

PowerMock

特点

PowerMock是一个扩展了其它如EasyMock等mock框架的、功能更加强大的框架。PowerMock使用一个自定义类加载器和字节码操作来模拟静态方法、构造方法、final类和方法、私有方法、去除静态初始化器等等。

注解

@RunWith注解:powerMock

@PrepareForTest: 静态

@Mock:Mock注解创建了一个全部Mock的实例,所有属性和方法全被置空(0或者null)

@Spy:Spy注解创建了一个没有Mock的实例,所有成员方法都会按照原方法的逻辑执行,直到被Mock返回某个具体的值为止。

注意:@Spy注解的变量需要被初始化,否则执行时会抛出异常

@InjectMocks:InjectMocks注解创建一个实例,这个实例可以调用真实代码的方法,其余用@Mock或@Spy注解创建的实例将被注入到用该实例中。

@Captor:Captor注解在字段级别创建参数捕获器。但是,在测试方法启动前,必须调用MockitoAnnotations.openMocks(this)进行初始化

@PowerMockIgnore注解

为了解决使用PowerMock后,提示ClassLoader错误。

使用

Final

当模拟final类或final方法时,需要使用这两个注解@RunWith和@PrepareForTest注解

@RunWith(PowerMockRunner.class)

@PrepareForTest({TargetClass.class})

Circle circle = PowerMockito.mock(Circle.class);
复制代码

Static

必须使用“@RunWith”和“@PrepareForTest”注解

PowerMockito.mockStatic(Class clazz);
复制代码

Spy

模拟类的部分方法

我们只希望模拟它的部分方法,而希望其它方法跟原来一样,可以使用PowerMockito.spy方法代替PowerMockito.mock方法。于是,通过when语句设置过的方法,调用的是模拟方法;而没有通过when语句设置的方法,调用的是原有方法。

PowerMockito.spy(Class clazz);
复制代码

模拟对象的部分方法

T PowerMockito.spy(T object);
复制代码

When语句

when().thenReturn()模式

用于模拟对象方法,先执行原始方法,再返回期望的值、异常、应答,或调用真实的方法。

// 返回期望值
PowerMockito.when(mockObject.someMethod(someArgs)).thenReturn(expectedValue);

// 返回期望异常
PowerMockito.when(mockObject.someMethod(someArgs)).thenThrow(expectedThrowable);

// 期望应答
PowerMockito.when(mockObject.someMethod(someArgs)).thenAnswer(expectedAnswer);

// 调用原方法
PowerMockito.when(mockObject.someMethod(someArgs)).thenCallRealMethod();
复制代码

doReturn().when()模式

用于模拟对象方法,在SPY实例下:直接返回期望的值、异常、应答,或调用真实的方法,无需执行原始方法

PowerMockito.doReturn(expectedValue).when(mockObject).someMethod(someArgs);



PowerMockito.doThrow(expectedThrowable).when(mockObject).someMethod(someArgs);



PowerMockito.doAnswer(expectedAnswer).when(mockObject).someMethod(someArgs);



PowerMockito.doNothing().when(mockObject).someMethod(someArgs);



PowerMockito.doCallRealMethod().when(mockObject).someMethod(someArgs);
复制代码

whenNew模拟构造方法

PowerMockito.whenNew(MockClass.class).withNoArguments().thenReturn(expectedObject);

PowerMockito.whenNew(MockClass.class).withArguments(someArgs).thenReturn(expectedObject);
复制代码

参数匹配器

任意值

Mockito提供Mockito.anyInt()、Mockito.anyString、Mockito.any(Class clazz)等来表示任意值。

参数匹配

当我们使用参数匹配器时,所有参数都应使用匹配器。如果要为某一参数指定特定值时,就需要使用Mockito.eq()方法。

符加匹配器

Mockito的AdditionalMatchers类提供了一些很少使用的参数匹配器,我们可以进行参数大于(gt)、小于(lt)、大于等于(geq)、小于等于(leq)等比较操作,也可以进行参数与(and)、或(or)、非(not)等逻辑计算等。

verify语句

验证是确认在模拟过程中,被测试方法是否已按预期方式与其任何依赖方法进行了交互。

用于模拟对象方法,直接返回期望的值、异常、应答,或调用真实的方法,无需执行原始方法。

Mockito.verify(mockObject[,times(int)]).someMethod(somgArgs);
复制代码

验证方法调用

        mockList.clear();
        Mockito.verify(mockList).clear();
复制代码

验证方法调用次数

timess、atLeastOnce、atLeast、only、atMostOnce、atMost等次数验证器。

        mockList.clear();
        Mockito.verify(mockList, Mockito.times(1)).clear();
复制代码

验证调用顺序

InOrder inOrder = Mockito.inOrder(mockedList);
        inOrder.verify(mockedList).add(1);
        inOrder.verify(mockedList).add(2);
        inOrder.verify(mockedList).add(3);
复制代码

验证调用参数

ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class);
        Mockito.verify(mockedList, Mockito.times(3)).add(argumentCaptor.capture());
复制代码

确保验证完毕

Mockito提供Mockito.verifyNoMoreInteractions方法,在所有验证方法之后可以使用此方法,以确保所有调用都得到验证。如果模拟对象上存在任何未验证的调用,将会抛出NoInteractionsWanted异常。

验证静态方法

PowerMockito.verifyStatic(StringUtils.class);
复制代码

私有属性

ReflectionTestUtils.setField方法设置私有属性值。

 ReflectionTestUtils.setField(userService, "userLimit", expected);
复制代码

可以采用Whitebox.setInternalState方法设置私有属性

 Whitebox.setInternalState(userService, "userLimit", expected);
复制代码

私有方法

通过模拟方法stub(存根),也可以实现模拟私有方法。但是,只能模拟整个方法的返回值,而不能模拟指定参数的返回值。

PowerMockito.stub(PowerMockito.method(UserService.class, "isSuperUser", Long.class)).toReturn(!expected);
复制代码

测试

Method method = PowerMockito.method(UserService.class, "isSuperUser", Long.class);
        Object actual = method.invoke(userService, userId);
复制代码

验证

PowerMockito.verifyPrivate(userService).invoke("isSuperUser", userId);
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享