网站美工建设意见,广东短视频seo搜索哪家好,廊坊公司做网站,oray免费域名注册公司要求提升单元测试的质量#xff0c;提高代码的分支覆盖率和行覆盖率#xff0c;安排我研究单元测试#xff0c;指定方案分享并在开发部普及开。
单元测试中的Mock的目的
Mock的主要目的是让单元测试Write Once, Run Everywhere.
即编写一次后#xff0c;可以在任意时…
公司要求提升单元测试的质量提高代码的分支覆盖率和行覆盖率安排我研究单元测试指定方案分享并在开发部普及开。
单元测试中的Mock的目的
Mock的主要目的是让单元测试Write Once, Run Everywhere.
即编写一次后可以在任意时刻任意环境运行无需依赖数据库网络等。
Mock工具介绍
Mock工具经过调研基本上是表格下面的这么个情况 简要介绍下各个的特点和为什么没选
rap2和easy-mock等都是基于node开发的和我们开发部的主力语言Java相性一般后续改造难度大并且不支持请求超时的配置和上下文的配置优点是使用操作简单pass。 wiremock和rap2差不多就是多个支持延时请求不过是英文的pass。 mock-server基于java语言的底层是netty编程自由比较适合java技术栈的团队。 postman虽然有mock功能但是只能针对某个请求的返回固定mock并且每次启动mock的端口和url完全随机无法接受pass。 我们最后选的是mockito和mock-servermockito因为是java的mock工具包所以并不在上面的表格里。
mockito 相关介绍
这个包是spring官方也推荐的Mock依赖在spring-boot-starter-test中默认就会自动包含。 这个包提供的相关类主要功能就是对某个对象进行mock通过其提供的特殊的语法对某个对象的返回以及行为做Mock。
应用场景
单元测试时如果依赖其他系统的RPC调用比如feign或dubbo可以针对相关RPC的调用对象进行直接Mock直接返回成功、超时、异常减少依赖。
在对系统内部的某些工具类或者数据库层进行单元测试时可以模拟一些异常情况比如数据库超时、框架层抛出某些很难复现的特定异常返回可以通过直接Mock实现来达到效果。
mockito除了Mock外也支持spyMock与spy的区别是Mock产生的是一个空对象对mock对象未做配置的方法调用均返回null或异常。
spy产生的是一个代理对象对那些做了配置的方法按照配置的预期返回未做配置的方法直接会调用原方法。
使用方式spring
maven中引入
dependencygroupIdorg.mockito/groupIdartifactIdmockito-all/artifactIdversion1.9.5/versionscopetest/scope
/dependency在测试类中进行如下定义
//需要mock的服务一般是RPC也可以是工具类总而言之是一个对象
Mock
TestRpc testRpc;
Autowired
TestService testService;//在Before中对其进行初始化
Before
public void initMocks() throws Exception {//1.1 初始化的api在这一步执行后testRpc被初始化为一个mock对象MockitoAnnotations.initMocks(this);//1.2 使用mock对象替换spring中的bean这里是将后面要用到的testService中的testRpc这个rpc对象//替换为上面Mock为我们创建的mock对象然后我们就可以对这个对象进行mock了这里的替换是spring容器级别的替换//注意理论上对RPC的service进行mock即可即替换调用RPC的那个bean中的rpc对象。ReflectionTestUtils.setField(AopTargetUtils.getTarget(orderPayFacade), testRpc, testRpc);//1.3 定义mock返回对新的mock对象进行定义当后续请求这个rpc的该方法时会直接return一个空的成功对象final ResultRpcTestVO testVo new ResultRpc();when(testRpc.getAccountByBindCardId(101010)).thenReturn(testVo);
}或者
//另一种初始化方式更加简单快捷
//这里是另一种写法设置一个默认的answer不用每个方法都设置一次返回,也可以继续进行上面那种方式的when配置
final TestRpc testRpcMock mock(TestRpc.class, new AnswerTestRes() {Overridepublic TestRes answer(InvocationOnMock invocationOnMock) throws Throwable {final TestRes testRes new TestRes();testRes.setConfigId(0L);testRes.setCityId(86);testRes.setServiceId(01);testRes.setSysJoinType(0);testRes.setMerchantId(320212018002);testRes.setMerchantCode();return testRes;}
});
ReflectionTestUtils.setField(AopTargetUtils.getTarget(testService), testRpc, testRpcMock);然后直接正常执行测试即可。
使用方式spring-boot及以上
前面说了spring-boot-starter较高版本2.0以上的test中默认会包括该依赖所以直接使用就行更方便的是无需使用反射工具替换spring上下文的bean使用MockBean注解标识bean即可。
mock-server 相关资料
官方文档 https://www.mock-server.com/
应用场景
当进行单元测试时如果我们需要进行http请求级别的模拟以及Mock那么我们就可以使用mockserver。
当然mockito也可以通过直接Mock那些http请求的类来达到相似效果不过使用mock-server我们可以更逼真的模拟http的环境以提前发现那些只有在使用网络下才会出现的问题。
既可以集成在maven的test生命周期里也可以直接单独启动做一个server。
使用方式
maven中引入
dependencygroupIdorg.mock-server/groupIdartifactIdmockserver-netty/artifactIdversion5.11.1/version
/dependency在测试类中进行如下定义
private final int mockPort 19999;
private ClientAndServer mockServer;
//在Before中对其进行初始化
Before
public void initMocks() throws Exception {//1.1 初始化的api启动mockservermockServer startClientAndServer(mockPort);//1.2 配置mockServermockServer.when(request().withMethod(POST).withPath(/test/pay_v1/trade/pay).withContentType(MediaType.APPLICATION_JSON)).respond(new TestResponseCallBack());
}
public static class TestResponseCallBack implements ExpectationResponseCallback{private final Gson gsonnew Gson();Overridepublic HttpResponse handle(HttpRequest httpRequest) throws Exception {log.info(------------{},httpRequest);if (httpRequest.getMethod().getValue().equals(POST)) {//校验签名boolean verify doVerifySign(httpRequest);if (!verify){return response().withStatusCode(OK_200.code()).withBody(gson.toJson(CommonResult.failure(CommonErrors.SIGNATURE_VERIFY_FAIL)));}//构造返回return createResponse(httpRequest);} else {return notFoundResponse();}}private HttpResponse createResponse(HttpRequest httpRequest) throws Exception {final HttpRequest httpRequest1 httpRequest;final String req new String(httpRequest.getBodyAsRawBytes());String respBody;final JSONObject jsonObject JSON.parseObject(req);//比如对参数做一些校验Assert.assertNotNull(jsonObject.getString(user_id));//构造返回可以根据请求的内容构造这里随便写个返回final String user_id jsonObject.getString(user_id);respBody{\success\: true,\errcode\: \0000\,\errmsg\: \成功\,\result\: {\user_id\: \123456\,\reserved\:user_id\\}};//这里如果必要的话也可以触发一个延时的回调new Thread(new Runnable() {Overridepublic void run() {LockSupport.parkNanos(1000000000L*2);final String notify_url jsonObject.getString(notify_url);HttpHeaders headers new HttpHeaders();headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON);headers.add(Accept, MediaType.APPLICATION_JSON.toString());JSONObject param new JSONObject();param.put(username, 123);HttpEntityString formEntity new HttpEntityString(param.toJSONString(), headers);String result new RestTemplate().postForObject(notify_url, formEntity, String.class);log.info(发送回调{},param.toJSONString());}}).start();return response().withStatusCode(OK_200.code()).withBody(respBody);}private boolean doVerifySign(HttpRequest httpRequest) throws Exception {String signature httpRequest.getFirstHeader(RequestHeader.Signature);String message new String(httpRequest.getBodyAsRawBytes(), StandardCharsets.UTF_8);String md5HexMessage DigestUtils.md5Hex(message.getBytes(StandardCharsets.UTF_8));return RSAUtils.doCheck(md5HexMessage, signature, privateKey, StandardCharsets.UTF_8.displayName());}
}然后直接正常执行测试即可。
cobertura-maven-plugin
前面的2个Mock工具结合cobertura-maven-plugin可以瞬间跑起一个带代码覆盖率的测试。
使用方式
maven
plugingroupIdorg.codehaus.mojo/groupIdartifactIdcobertura-maven-plugin/artifactIdversion2.7/version
/plugin执行测试mvn clean cobertura:cobertura -f pom.xml。
到target/site下打开index文件查看结果 总结
本文简单介绍了3个工具的使用主要是提供了一个可行的方案去推进单元测试具体3个工具的详细使用细节以及进阶可以自行查找资料。
最后感谢每一个认真阅读我文章的人礼尚往来总是要有的虽然不是什么很值钱的东西如果你用得到的话可以直接拿走 这些资料对于【软件测试】的朋友来说应该是最全面最完整的备战仓库这个仓库也陪伴上万个测试工程师们走过最艰难的路程希望也能帮助到你