转眼一个月多没写博客了,这可不行啊,需要有产出激励自己才好。

maven依赖(结合Junit使用示例)

<!-- https://mvnrepository.com/artifact/org.powermock/powermock-api-mockito -->
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.6.5</version>
    <scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.powermock/powermock-module-junit4 -->
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.6.5</version>
    <scope>test</scope>
</dependency>

基础使用

mock、spy、when、verify

上述几个都是Mockito的常用静态方法

  • 通过PowerMockito.mock(Class<T> clazz)可以创建一个mock的对象实例
  • 对Mock的对象,使用类似PowerMockito.when(mockObject.someMethod(someArg)).thenReturn(resultYouExpected)的语法,我们可以mock对象的行为的返回值。需要注意的是:mock的对象,所有没有调用when设置过的方法,在测试时调用,返回的都是对应返回类型的默认值
  • 测试时,希望对行为进行验证,可以使用类似PowerMockito.verify(mockObject[,times(int)]).someMethod(somgArgs)的语法,验证mock的对象,方法是否执行过,执行过几次。
  • 特别的,对于希望调用后什么都不做的,或者抛出异常的,可以使用PowerMockito.doNothing().when(...)...doThrow(Throwable).when(...)...的语法
  • 如果一个对象,只希望mock它的部分方法,而其他方法希望和真实对象的行为一眼,可以使用PowerMockito.spy(Class<T> clazz)代替PowerMockito.mock(Class<T> clazz)方法,其后的设置依旧,这时,没有通过when设置过的方法,测试调用时,行为和真实对象一样

通配符

可能存在这种情况:测试时对于传入的参数或者传出的参数并不关心,这时可以使用通配符:通过PowerMockito.anyInt()PowerMockito.anyString、甚至PowerMockito.any(Class<T> clazz)……来表示任意值,**需要注意的是,如果一个方法中,有一个地方使用了通配符,其他参数也都要使用通配符,对于特定的参数,不能直接指定,而需要使用PowerMockito.eq(someArg)来通配这个参数

测试私有方法、静态方法、final方法

PowerMockito较之Mockito更好的地方就是支持对私有方法,静态方法和final方法的Mock,使用方法是:


  1. 在测试类上使用注解@RunWith(PowerMockRunner.class)
  2. 在测试方法上使用注解@PrepareForTest(targetClassNeedMock.class)
  3. 分类讨论
    • 对于静态方法:@PrepareForTest的class是静态方法所在类,对这个类使用PowerMockito.mock(Class<T> hasStaticMethodClazz),之后对静态方法使用PowerMockito.when(mockObject.someStaticMethod(...))...mock,调用静态方法的被测试类即可被mock
    • 对于final方法:与静态方法类似,不过@PrepareForTest的class是final方法所在类
    • 对于私有方法:PowerMockito提供了对私有方法的mock,使用PowerMockito.when(mockObject,methodName:String,someArgs:Object)...来mock私有方法,这时@PrepareForTest的class是私有方法所在类

这里面需要注意的点是@PrepareForTest的class,它总代表需要特殊处理的类,而不一定是被测试类。需要特殊处理的类可能只是被测试类的一个成员变量,它可以在mock后自动注入被测试类中。

修改私有属性

在Mockito1.x和2.x,修改私有属性的方法略有不同

  • 1.x的使用Whitebox.setInternalState(mockObject,"attributeName",mockAttributeBean)的方式可以设置私有属性
  • 2.x的使用FieldSetter.setField(mockObject,originAttrubuteBean,mockAttributeBean)的方式来设置,这个时候,需要先获得原先mock对象内的成员变量(:Field),所以便利性降低了

阻止静态方法的执行 @SupressStaticInitializationFor

一些静态块的代码,可能测试的时候不想让它们在类加载的时候执行,这个时候,可以使用@SuppressStaticInitializationFor("会执行静态方法的全限定名")来阻止执行

使用注解

通过使用注解来减少重复代码,使用注解,需要初始化它们,在@Before中使用MockitoAnnotations.initMocks(testClass) 来初始化
1. 使用@Mock注解声明替代mock方法
2. 使用@Spy替代spy方法
3. 使用@InjectMocks,将@Mock和@Spy的对象注入到被@InjectMocks标注的测试对象中

Spring结合

结合SpringJUnit

很多工程都会使用到Spring,这个时候,想要测试代码,需要@Runwith(SpringJUnit4ClassRunner.class),但是PowerMockito也需要Runwith注解。这种情况,PowerMockito提供了新的注解@PowerMockRunnerDelegate
使用

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)

来允许另一个Junit Runner运行

结合Spring 注解执行

我们既希望有Spring自动注入的便利,有希望有PowerMockito的便利,通过注解的配合,二者可以兼得。
对于@Spy@InjectMocks标注的对象,它们同时还可以使用@Autowired标注,这时,没有被mock的部分,将会从Spring注入进来,这些对象表现如同真实对象一样。

参考来源

  1. 使用Mockito进行单元测试【1】——mock and verify
  2. 使用Mockito进行单元测试【2】—— stub 和 高级特性
  3. PowerMockito使用详解
  4. 学习Mockito - Mockito对Annotation的支持
  5. powermock如何阻止静态代码块和调用私有方法
  6. Delegate to another JUnit Runner
  7. Spring中如何使用Mockito做单元测试
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐