mock,模拟服务器发送数据,通常会在以下两种场景会用到:当后端接口未实现完毕,前端却迫切需要一个接口的数据以继续开发时,就需要一个临时接口来模拟后端接口返回符合前后端文档规范的数据结果;如果后端需要测试第三方api时,服务尚未开通完毕或者调试接口也计调用次数,就需要临时接口来模拟该接口了,以此来实现整个代码编写逻辑更加通顺。
现有的mock解决方案
mock的解决方案也有很多,比如使用知名的postman工具,除了可以主动发送请求http或者websocket请求之外,也可以启用一个mock服务器。所需要做的主要就两步,创建一个mock server,然后在collections中按照规则去设计一些返回结果即可,如下图所示。前端使用时的服务器地址可从mock server页签中得到。
当然,于postman来说,每天只有1000次的mock测试次数,看起来很多,实际上各种接口反复调试,很快就能用完,尤其是一些调用频率高的接口。所以并不是那么好用。
如果是前端使用vscode开发,有一个很好用的插件 easymock,语法配置上来说也是非常的方便,启动mock服务器只需要在vscode的命令中run easymock即可。不过对于后端mock第三方接口来说,还要启动一个前端IDE,占用内存不说,还不方便管理,对于一些复杂的逻辑实现起来可能会比较麻烦。
而mock.js可以说是知名度很高了,其语法被广泛运用与各种mock服务中,只需要node启动即可,对于前端调试接口来说可以说是利器。而对于后端mock第三方接口来说,还是需要单独开启一个服务,并且复杂的返回逻辑编写较为困难,使用起来并不方便。
我的方案
对于前端来说,上面的easymock或者mock.js都是非常好用的,而后端测试三方接口却都感觉有些力不从心。所以就需要一种新的方案来解决这种问题,先来列出来想要达成的效果:
- 能够mock第三方接口,返回数据
- 希望不开启额外的服务,使用后端同一进程端口
- 能够处理复杂的逻辑,返回复杂的结果
- mock的接口在正式环境中不可被访问
- 易于管理,修改方便,与后端工程一起git管理
实现的方式就是使用:profile。
首先我们需要至少两个application的yml配置文件,分别是开发环境和正式环境,正式环境的第三方地址为实际的第三方api的请求前缀url,而开发环境的第三方地址设置为本地地址,这样实现了灵活切换环境。
接着是使用@Profile注解,加在所有的mock接口类上,这样在prod环境下,这个接口类就不会被注册到:
代码语言:javascript复制/**
* 登录mock
*/
@Profile("test")
@RestController
public class LoginMock {
/**
* 登录获取unionid
* @param map -
* @return -
*/
@PostMapping(ReqURI.CODE2SESSION)
public DYCode2SessionResult login(@RequestBody Map<String, String> map){
String code = map.get("code");
if ("success".equals(code)) {
return new DYCode2SessionResult(0,"success",
new DYCode2SessionResult.ResData(
"hZy6t19VPjFqm","V3WvSshYq9","",
"f7510d9ab" ((int)(Math.random()*10)%2)
)
);
} else {
return new DYCode2SessionResult(40015,"bad appid",
new DYCode2SessionResult.ResData(
"","","",""
)
);
}
}
}
其中, @PostMapping(ReqURI.CODE2SESSION) ,并没有直接编写uri,而是统一管理到了 ReqURI 请求路径静态常量中管理了,该地址除了在这个mock中有使用到,在实际调用侧也用到。
代码语言:javascript复制String path = serverProperties.getDouYin().getAPI() ReqURI.CODE2SESSION;
JSONObject jsonObject = new JSONObject();
jsonObject.put("appid", serverProperties.getDouYin().getAppID());
jsonObject.put("secret", serverProperties.getDouYin().getSecret());
jsonObject.put("code", code);
jsonObject.put("anonymous_code", "");
DYCode2SessionResult result = restTemplate.postForObject(path, jsonObject, DYCode2SessionResult.class);
ServerProperties的定义如下所示,是一个配置类。
代码语言:javascript复制package top.dreamcenter.dyenglish.entity;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 服务器基础配置
*/
@Data
@ConfigurationProperties(prefix = "top.dreamcenter.server")
public class ServerProperties {
// 抖音设置
private DouYin douYin;
// 房间设置
private Room room;
@Data
public static class DouYin {
// 抖音接口url前缀
private String API;
// 抖音应用appId
private String appID;
// 抖音应用secret
private String secret;
}
@Data
public static class Room {
// 核心线程数
private Integer corePoolSize;
// 最大线程数
private Integer maxPoolSize;
// 队列容量
private Integer queueCapacity;
// 题目数量
private Integer questionCount;
// 题目间隔时间
private Integer questionIntervalSeconds;
}
}
通过这种方式就成功实现了第三方的接口mock,在管理上可以直接与原工程一起参与git;接口发生修改时,更改ReqURI中的成员即可;而上线后只需要 -Dspring.profiles.active=prod 即可切换到官方的url,并且测试用mock接口不被暴露出来。
非常的nice!