Java测试笔记:Junit4+PowerMockito
测试的 AAA 步骤
分为三步:Arrange, Act, Assert
- Arrange(准备)
- mock / stub 依赖
System.setProperty(...)、准备测试数据- 反射
getDeclaredMethod/Field/Constructor setAccessible(true)
- Act(执行)
- 调用被测 public 方法
- 或(确实要测 private 时)
method.invoke(...)
- Assert(断言)
assertEquals/assertTrue/...verify(...) / verifyStatic(...) / verifyPrivate(...)
setAccessible(true)通常算 Arrange;invoke(...)算 Act。
反射:private 构造器 / private 方法的测试
private 构造器:反射创建实例
1 | |
private 方法:反射调用并断言返回值
1 | |
验证 public 非 static 函数
Mockito 先 mock 出一个对象,然后 verify 就行了。
1 | |
验证 public static 函数
包含四个部分:
- 注解测试类
@RunWith(PowerMockRunner.class) - 准备被测试类
@PrepareForTest(MyClass.class) - 开启模拟
PowerMockito.mockStatic(MyClass.class) - 验证
PowerMockito.verifyStatic
假设你有一个工具类 StaticUtils,里面有一个静态方法 sendNotification(String msg)。
1 | |
- PowerMockito.mockStatic(MyClass.class) 会把该类所有 static 方法置于 mock 状态,即默认doNothing
- verifyStatic后面必须紧跟一次被测试的方法调用,否则验证会失败。
- static函数可能修改static属性,可能对其他tests有影响
spy 打桩
spy 的典型场景是:
- 想保留真实对象的大部分行为,但只替换/拦截其中一小部分(部分 mock)
- 相比 mock()(全是假),spy()(大部分是真的)
public方法
屏蔽内部函数
1 | |
stub返回值
1 | |
private 方法
测试类加上
@RunWith(PowerMockRunner.class)@PrepareForTest(MyClass.class)
使用 PowerMockito 代替 Mockito 来 spy 和 verify,并且 when 需要改变
1 | |
suppress 不执行方法
1 | |
- func2不会被执行
- 无法再用 verifyPrivate 来统计调用次数
拦截构造过程 whenNew
三个前置条件:
- 注解测试类
@RunWith(PowerMockRunner.class) - 准备被测试类
@PrepareForTest(MyClass.class)- 必须在注解里放入调用 new 关键字的那个类,而不是被 new 的类
- 抛出异常:
whenNew会抛出 Exception,所以测试方法必须加上throws Exception
1 | |
TooManyConstructorsFoundException
当被测试类有多个构造函数时,PowerMockito 无法确定要 mock 哪个构造函数,就会抛出 TooManyConstructorsFoundException。 解决方法:
- 在
whenNew里指定构造函数参数类型:.withParameterTypes(...)
Mockito 参数匹配小抄
any():匹配任何对象(包括 null)- 内置类型的匹配器:
anyInt(),anyLong(),anyDouble(),anyBoolean(),anyString()…
any(Class<T> type):匹配任何指定类型的对象(包括 null)- 比如
any(TimeUnit.class),any(String.class)
- 比如
import 不会触发类的 static 初始化
import MyClass; 只是编译期语法糖,不会执行 static { ... }。
触发类初始化(从而执行 static {})的常见操作:
- 访问 static 字段:
MyClass.SOME_FIELD - 调用 static 方法:
MyClass.someMethod() - 反射
Class.forName(...) - 其他类的 static 初始化间接引用