写点什么

一文带你了解 Mock 技术体系

  • 2024-06-26
    江西
  • 本文字数:2646 字

    阅读完需:约 9 分钟

简介

为什么要学习 Mock

  • 提高测试深度

  • 提高测试效率

  • 降低成本


  1. 测试股票软件,模拟当天股票全部上涨

  2. 测试股票软件,模拟当天股票全部下跌

  3. 测试股票软件,模拟部分股票涨幅 10%


获取更多技术资料,请点击!

Test Double 测试替身

  • Dummy 占位对象 对象被传递但从未实际使用过。通常它们仅用于填充参数列表。

  • Fake 假对象 对象实际上有工作实现,但通常采取一些捷径,这使得它们不适合生产(内存数据库就是一个很好的例子)。

  • Stubs 桩对象 为测试期间调用提供预设答案,通常根本不响应任何超出测试程序的内容。

  • Spies 间谍对象 它们还根据调用方式记录一些信息。其中一种形式可能是电子邮件服务,它记录发送了多少消息。

  • Mocks 模拟对象 是我们在这里谈论的:预先编程的对象,这些期望形成了它们期望接收的调用的规范。

** **

测试替身关键概念的区别

一个真实的技术架构例子

  • dummy 只要端口开着就行

  • fake 内存数据库

  • spy UI 界面后端请求记录

  • stub 假的登录后端服务

  • hook 新用户判断方法修改

  • proxy 代理转发机制

  • mock 模拟对象


** **

Fake 假对象 定义

Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an InMemoryTestDatabase is a good example).


假对象实际上有工作实现,但通常采取一些捷径,这使得它们不适合生产(纯内存数据库就是一个很好的例子)。


Fake 应⽤场景

** **

Stub 桩定义

Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test.


为测试期间调用提供预设答案,通常根本不响应任何超出测试程序的内容。


Stub 应⽤场景 Swagger

Setup Stub Server

java -jar moco-runner-1.2.0-standalone.jar http -p 12345 -c foo.json
{ "request" : { "uri" : "/foo", "queries" : { "param" : "blah" } }, "response" : { "text" : "bar" }}
复制代码


Mock 模拟对象定义

Mocks are pre-programmed with expectations which form a specification of the calls they are expected to receive. They can throw an exception if they receive a call they don't expect and are checked during verification to ensure they got all the calls they were expecting.


模拟预编程了期望,这些期望形成了他们期望接收的调用的规范。如果他们收到了他们不期望的调用,他们可以抛出异常,并在验证过程中进行检查以确保他们得到了他们期望的所有调用。


** **

Mock 两种应用场景

  • mock on stub:按需返回期望数据

  • mock on proxy:按需返回真实数据的修改副本


常⽤的 Mock 工具

  • Charles 测试工程师常用

  • BurpSuite 黑客常用

  • Fiddler 只能 Windows 上使用

  • Nginx 服务器反向代理与修改

  • Mitmproxy 代理工具 可编程

  • Wiremock 代理工具 可编程


mitmproxy

mitmproxy is a set of tools that provide an interactive, SSL/TLS-capable intercepting proxy for HTTP/1, HTTP/2, and WebSockets.


mitmproxy mock on proxy

python3 -m http.servermitmdump -p 8001  -m reverse:127.0.0.1:8000 --flow-detail 4 -B '/~bs .*Directory.*/Directory/ceshiren.com mock'
复制代码


mitmproxy 强大的插件机制 Addons

  • dns

  • tcp

  • cert

  • http/https

  • websocket



adb mock 案例



import sys
from mitmproxy import ctxfrom mitmproxy import tcpfrom mitmproxy.utils import strutilsfrom mitmproxy.tools.main import mitmdump

def tcp_message(flow: tcp.TCPFlow): message = flow.messages[-1] old_content = message.content message.content = old_content.replace( b":0;localabstract:webview_devtools_remote_", b": 0;localabstract:xweb_devtools_remote_" )
ctx.log.info( "[tcp_message{}] from {} to {}:\n{}".format( " (modified)" if message.content != old_content else "", "client" if message.from_client else "server", "server" if message.from_client else "client", strutils.bytes_to_escaped_str(message.content)) )

if __name__ == '__main__': sys.argv = ["", "-p", "5038", "--rawtcp", "--mode", "reverse:http://localhost:5037/", "-s", sys.argv[0], "-vv"] mitmdump()
复制代码

WireMock

The flexible tool for building mock APIs.


Create stable development environments, isolate yourself from flakey 3rd parties and simulate APIs that don't exist yet.


** **

wiremock stub

java -jar wiremock-jre8-standalone-2.33.2.jar
复制代码


{  "request": {    "method": "GET",    "url": "/wiremock"  },  "response": {    "status": 200,    "body": "Easy!"  }}
复制代码

** **

mock on stub


@Testpublic void exactUrlOnly() { stubFor(get(urlEqualTo("/some/thing")) .willReturn(aResponse() .withHeader("Content-Type", "text/plain") .withBody("Hello world!")));
assertThat(testClient.get("/some/thing").statusCode(), is(200)); assertThat(testClient.get("/some/thing/else").statusCode(), is(404));}
复制代码

mock on proxy


wm.stubFor(get(urlPathEqualTo("/templated")) .willReturn(aResponse() .proxiedFrom("$!request.headers.X-WM-Proxy-Url") .withTransformers("response-template")));
复制代码




    public class ExampleTransformer extends ResponseDefinitionTransformer {

    @Override public ResponseDefinition transform(Request request, ResponseDefinition responseDefinition, FileSource files, Parameters parameters) { String content=responseDefinition.getTextBody().replace("霍格沃兹", "mock"); System.out.println(responseDefinition.getTextBody()); System.out.println(content); return new ResponseDefinitionBuilder() .withHeader("MyHeader", "Transformed") .withStatus(200) .withBody(content) .build(); }

    @Override public String getName() { return "hogwarts_mock"; }}
    复制代码

    ** **

    总结

    • 了解测试替身的实现方式,统一沟通概念

    • 了解 Mock 的常见应用场景

    用户头像

    社区:ceshiren.com 微信:ceshiren2021 2019-10-23 加入

    微信公众号:霍格沃兹测试开发 提供性能测试、自动化测试、测试开发等资料,实时更新一线互联网大厂测试岗位内推需求,共享测试行业动态及资讯,更可零距离接触众多业内大佬。

    评论

    发布
    暂无评论
    一文带你了解Mock 技术体系_霍格沃兹测试开发学社_InfoQ写作社区