最近研究了下阿里出品的Mock工具TestableMock,感觉在Mock这块儿,它是真的比现有的Mock工具强悍太多了。
官网简介:
官网说:开发者真正关心的只有一件事,"这个调用,在测试的时候要换成那个假的Mock方法"。
但我觉得还得补充上一句,开发者还关心能够很方便地Mock出依赖的第三方返回不同结果的情况。
现在,假设我们有个业务代码findByCondition所在的被测试类AService:
public class AService{
private RPCService rpcService;
publice Boolean findByCondition(JsonObject query){
// doSomething...
// and doSomething...
RPCResult rpcResult = rpcService.query(query);
if(rpcResult.code = "Success"){
// doSomething...
}else {
// doSomething...
}
}
}
这是一个很常见的业务场景,依赖第三方的返回结果来决定业务的走向。我们在写单测的时候,需要把RPC调用过程给Mock出来,同时要能模拟出RPC响应不同结果的情况。
如果用旧的Mock工具,可以通过When Then语法定义出Mock在不同参数下的响应值,类似于这样:
when(mIntent.getAction()).thenReturn("com.yn.test.mockito");
when(mIntent.getStringExtra("Name")).thenReturn("Whyn");
需要预定义每种情况下的请求参数,而且写过单测的就知道,参数的字段少的时候还行,多的时候,构建参数就已经是一件很麻烦的事情了,更麻烦的是,如果要命中这个When条件,基本上所有字段都需要符合才行,懂得都懂。
我个人感觉testable强就强在,它可以很方便地定义在各种情境下的返回值,这是官网的说明
简单来说,通过 MOCK_CONTEXT 为Mock设置测试场景,在Mock方法中设置针对不同场景的响应。那上述被测试类的单测就可以这么写:
public class AServiceTest{
private AService aService = nwe AService();
// 放置Mock方法的地方
public static class Mock {
// 使用`targetMethod`指定需Mock的方法名
// 此方法本身现在可以随意命名,但方法参数依然需要遵循相同的匹配规则
@MockInvoke(targetClass = RPCService.class, targetMethod = "query")
private RPCResult query(JsonObject query) {
switch((String)MOCK_CONTEXT.get("RPC调用")) {
case "查询有结果":
List<String> list = new ArrayList;
list.put("1");
list.put("2");
list.put("3");
return new RPCResult(list);
case "查询结果为空":
List<String> list = new ArrayList;
list.put("1");
list.put("2");
list.put("3");
return new RPCResult(list);
case "RPC调用异常":
throw new NetworkException();
default:
return null;
}
}
}
@Test
publice Boolean testFindByCondition(JsonObject query){
MOCK_CONTEXT.put("RPC调用", "查询有结果");
assertEquals(true, aService.findByCondition());
MOCK_CONTEXT.put("RPC调用", "查询结果为空");
assertEquals(false, aService.findByCondition());
MOCK_CONTEXT.put("RPC调用", "RPC调用异常");
assertEquals(false, aService.findByCondition());
}
}
这个写法的好处:
1、Mock的方法跟测试代码分离,测试方法中就只剩定义要测试的情景跟预期的结果即可
2、在定义Mock方法的时候,返回值跟入参解偶,不再需要花费心思去关注测试方法的入参是不是命中了when条件
3、Mock方法可以复用,这个可以参考官方文档
这样写Mock是不是很清晰了呢