TestableMock 简介
官方介绍"一款特立独行的轻量 Mock 工具,以简化 Java 单元测试为目标的综合辅助工具集"
Maven 项目中使用
在dependencies列表添加 TestableMock 依赖
<dependency>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-all</artifactId>
<version>0.7.9</version>
<scope>test</scope>
</dependency>
最后在build区域的plugins列表里添加maven-surefire-plugin插件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-javaagent:${settings.localRepository}/com/alibaba/testable/testable-agent/0.7.9/testable-agent-0.7.9.jar</argLine>
</configuration>
</plugin>
TestableMock 可以 Mock 什么
快速 Mock 任意调用
官方介绍"使被测类的任意方法调用快速替换为 Mock 方法,实现"指哪换哪",解决传统 Mock 工具使用繁琐的问题"
使用场景
项目中有支付回调的场景,需要测试回调的方法逻辑是否正确。
痛点
方法中有调用其他 jar 包中的方法,而且该方法中还有很多逻辑,但这些逻辑并不是我们关注的
解决
待测方法
@Override
public String parseOrderNotifyResult(String xmlData) {
try {
WxPayOrderNotifyResult notifyResult = wxStudentMiniPayService.parseOrderNotifyResult(xmlData);
...
...
wxStudentMiniPayService.parseOrderNotifyResult(xmlData) 该方法为 maven 引入 jar 包中的方法,我们的目的就是 Mock 该方法,从而只关注 待测方法的逻辑
测试 case,直接看代码
@SpringBootTest
public class PayServiceImplTest extends AbstractTestNGSpringContextTests {
@Resource
private PayServiceImpl payService;
public static class Mock{
@MockInvoke(targetClass = WxPayService.class)
public WxPayOrderNotifyResult parseOrderNotifyResult(String xmlData) {
WxPayOrderNotifyResult wxPayOrderNotifyResult = new WxPayOrderNotifyResult();
wxPayOrderNotifyResult.setTransactionId("11111");
wxPayOrderNotifyResult.setResultCode("SUCCESS");
wxPayOrderNotifyResult.setOutTradeNo("74afe6ab214248b49898a832da79b742");
wxPayOrderNotifyResult.setDeviceInfo("KLASS");
return wxPayOrderNotifyResult;
}
}
@Test(description = "支付回调")
public void testParseOrderNotifyResult(){
String xmlData = "";
String res = payService.parseOrderNotifyResult(xmlData);
...
}
}
此时,执行测试 case,待测方法中WxPayOrderNotifyResult notifyResult = wxStudentMiniPayService.parseOrderNotifyResult(xmlData) notifyResult 返回的结果就是 Mock 容器中对应的数据。
上面代码,就是在测试类中添加了一个名称为 Mock 的静态内部类,拷贝原方法定义到 Mock 容器类,加@MockInvoke 注解。这也是官方推荐的最简单的做法
访问被测类私有成员
TestableMock 提供了 PrivateAccessor 工具类
访问私有方法
PrivateAccessor.invoke(任意对象, "私有方法名", 调用参数...) ➜ 调用任意类的私有方法
使用场景
通过公有方法间接测私有方法比较繁琐,公有方法有复杂的入参,核心业务逻辑在私有方法中,我们更加关注私有方法的业务逻辑。
痛点
未使用 TestableMock 时,我是修改了方法的可见性,private 变为 public,这种方法比较繁琐
解决
待测方法
private Student register(Map<String, String> paramMap) {
...
}
如何借助 PrivateAccessor 测试该私有方法呢?
@Test(description = "团购入口注册")
public void registerTest() {
Map<String, String> paramMap = new HashMap<String, String>(){
{
put("areaCode", "86");
put("mobile", "19900000007");
}
};
Student student = PrivateAccessor.invoke(groupService, "register", paramMap);
...
}
除了访问私有方法,还读取私有字段、修改私有字段、读取静态私有字段、修改静态私有字段、调用静态私有方法、调用私有构造方法,遇到真实使用场景再进行补充
持续更新中...