API mocking和服务虚拟化工具WireMock v2发布了。其中主要提升包括了改进的请求验证失败报告、可以创建自定义的请求匹配逻辑(包括使用Java 8 lambda表达式)、支持gzip请求体及响应体、随机分布的延迟(目前支持均匀分布以及对数正态分布)、cookie及基本认证报文头的匹配。
\\最近作者本人Tom Akehurst做客InfoQ,并解答了WireMock v2的新特性、服务虚拟化在现代化架构中所扮演的角色以及mocking和契约验证的关系等问题。
\\InfoQ:你好,Tom,欢迎来到InfoQ!你能简要介绍一下自己和WireMock项目么?
\\\\\Akehurst:大家好,我是Tom Akehurst。白天我在伦敦的Energized Work帮助客户构建更好的技术,晚上(和周末)我维护着WireMock。
\\我将WireMock描述为一个API mocking或服务虚拟化工具。实际上它能让你在测试时stub或mock你与所依赖的系统间的HTTP交互。这包含以下几个好处:
\\
- 让你在所依赖的API还未完成或根本不存在时不影响自身的生产力。\\t
- 减少对测试环境和第三方沙箱的依赖。\\t
- 比调用真实系统进行测试更快(可能是10倍或更多)地运行测试案例。\\t
- 方便地测试边界案例和故障模式,包括一些讨厌的东西如TCP连接断开和延迟峰值。\
可以在http://wiremock.org上找到相关文档和其他信息。
\
InfoQ:你能介绍一下WireMock最近的v2发布的新特性么?
\\\\\Akehurst:WireMock v2引入了stub定义和请求之间“距离”的概念。这使得在报告未匹配请求和失败验证上的一些重大改进成为可能。当一个验证请求无法得到匹配,WireMock会找到最相近的定义并显示出两者的不同。这大大减少了许多麻烦,如在测试完一个包含诸多HTTP POST请求的功能后,发现忘记大写一个字母。
\\现在扩展API更丰富了。响应转换可以接受参数并且可以转换代理响应。现在还可以使用自定义请求匹配逻辑,包括通过Java 8的lambda表达式。
\\虽然WireMock 1.x可以在安卓平台上运行,但这需要维护一个自己的分支并修改一些源码来绕开一些类库不兼容。多亏安卓社区一些人员的帮助,现在只需要在你的构建文件中加入几行代码就可以了。
\\其他记录的改变包括:
\\
- 支持gzip的请求体和响应体。\\t
- 随机分布的延迟,目前支持均匀分布以及对数正态分布。\\t
- cookie和基本认证报文头匹配。\\t
- 对stub映射的修改、删除和(重新)保存。\\t
- 升级到Jetty 9,提升了性能、更少令人头痛的Servlet API依赖以及bug修复。\\t
- 标准(standard)和独立(standalone)的JAR包在Maven仓库中成为分离的artifact,这意味着当你只依赖于独立JAR包时不必再排除大片多余的依赖。\
InfoQ:你认为有多少开发者意识到服务虚拟化技术(相对比于mocking或stubing),并且你能分享一下WireMock这类工具所擅长的用例么?
\\\\\Akehurst:快速看下Google趋势可以看到Mockito相比WireMock有大约10倍的搜索量。虽然有些不科学,但我认为可以说服务虚拟化的关注度要赶上对象mock还有一段距离。
\\但是对WireMock这类工具的兴趣在近一两年有显著的上升趋势。一个可能的解释是微服务的爆发式流行。我接触下来发现越来越多WireMock的用户在搭建微服务测试时使用它,不得不说这绝对是一个WireMock所擅长的用例。
\\其他WireMock能带来巨大价值的用例有:
\\
- 组件测试,以接近单元测试的速度对一个独立的服务、应用进行验收测试。虽然在系统边界可以替代使用对象mock,使用WireMock意味着HTTP客户端、资源池以及序列化反序列化都会被测试覆盖到。\\t
- 故障案例,如socket断开连接。这些使用对象mock工具很难正确地模拟,同样地很难在真实系统中模拟。\\t
- 隔离的性能测试,衡量单个组件的性能。虽然这里又一次可以在系统边界使用对象mock来替代,但是这样得出的结果很有可能是扭曲的,因为这忽略了HTTP客户端、连接池、线程等的影响。\
InfoQ:你能分享一些使用服务虚拟化工具如WireMock创建测试案例的“最佳实践”么?是否有特殊的方法论可作为WireMock驱动测试的补充,比如行为驱动开发?
\\\\\Akehurst:我在与WireMock用户交流和客户的工作中了解到:
\\
- 慎重使用录制、回放功能。就如同使用UI自动化工具一样,录制一些定期变化的内容很快就会产生许多需要维护的工作量。\\t
- 就像你为UI测试写页面对象(page objects)、围绕stub和验证代码写建造者(builder)和服务包装(service wrapper)一样,一开始有些费力,但是从长远来看,这会对方便维护和易读性带来收益。\\t
- 书写故障注入测试案例,断开连接、响应5xx错误、增加延迟造成socket超时。这些不仅仅帮你找出那些生产环境中半夜三点折磨你的问题,还能帮你检查你应用的健康检测和监控是否正确工作。如果你在JVM(或安卓)上运行,你可以以单元测试级的速度获得一个全范围的关于风险恢复能力的反馈,这绝对胜过使用Chaos Monkey进行测试来告诉你结果!\
WireMock与行为驱动开发工具能很好地合作。我见过也使用过的一个非常通用的模式是在一个场景的“Given”阶段配置stub,然后在“Then”阶段进行交互的验证。
\
InfoQ:你怎么看待服务虚拟化和契约优先开发的关系,这两者是否有重叠部分?
\\\\\Akehurst:由于我也是最近才接触这个,所以可能说得不太权威。看上去机器可读规范(如Swagger或RAML)对解决检测stub定义与事实间偏差的问题很有前景。
\\另一个有意思的方法是Spring契约校验器(Spring Contract Verifier)所带来的,它通过契约规范来生成WireMock的stub定义,这样就可以隔离客户端进行测试了。
\
InfoQ:你认为像WireMock这类工具对非功能性需求的测试是否有用?
\\\\\Akehurst:绝对有用!性能、可恢复性和安全这些都是我在使用WireMock进行测试和看别人测试时用到的特性。
\\举个例子,提出上面提到的随机延迟特性的pull request的是一个使用WireMock的团队,他们对他们微服务进行不间断的性能测试。他们的发布流程要求他们的每一个服务需要在发布到共享环境之前在隔离的环境中通过性能检测。
\\在可恢复性方面,有一次我在写浸泡测试案例时使用故障注入,显示了当一个第三方的系统返回代理错误时,应用在逐渐地泄漏连接池连接。
\
InfoQ:WireMock网站上提到你在创建一个名字叫MockLab的基于SaaS的提案。你能和InfoQ读者分享一些具体细节么?
\\\\\Akehurst:最近,越来越多用户提议我详细说明如何从零开始搭建WireMock。我也看到过一些团队投入巨大工作量来部署、管理大量的WireMock实例,以及在上层定制UI来辅助探索性的测试和演示。
\\MockLab的目标就是大大减少管理大量WireMock实例所需要的精力,用几次鼠标点击就能部署mock服务。这使得不懂代码的人员也可以进行测试的搭建和分析。
\\如果你正在搭建(或测试!)移动应用、微服务或依赖于第三方API的系统,我强烈推荐看一下这个项目。
\\如果希望了解更多或在MockLab可用时得到通知,请访问预发布网站:http://get.mocklab.io。
\
InfoQ:Tom,谢谢你与InfoQ的对话。你还有什么其他想和我们读者分享的么?
\\\\\Akehurst:我只想说非常感谢所有帮助过我完成发布v2的人。这都归功于http://wiremock.org/about/所列出的人员,我要特别感谢Sam Edwards、Rob Elliot和Rowan Hill,谢谢他们所付出的时间和耐心。谢谢大家!
\
更多关于WireMock v2的信息可以在项目网站找到,源码可以查看Tom Akehurst的GitHub账号。
\\查看英文原文:API Mocking Tool WireMock v2 Released with Improved Request Matching and Stub Management
\\感谢夏雪对本文的审校。
\\给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号:InfoQChina)关注我们。