一文带你了解Mock 技术体系

简介: **Mock和测试替身简介** 学习Mock提升测试深度、效率和降低成本。示例:测试股票软件时模拟市场涨跌。Test Double包括Dummy(占位)、Fake(简化的实现)、Stub(预设回答)、Spy(记录行为)和Mock(预编程期望)。Fake如内存数据库,适用于测试。Stub用于预设响应,如Swagger接口。Mock确保收到预期调用。常用Mock工具有WireMock、Mitmproxy等。WireMock用于构建模拟API,支持stub和proxy模式。掌握Mock技术能更好地隔离和测试系统组件。

简介

为什么要学习 Mock

  • 提高测试深度
  • 提高测试效率
  • 降低成本
  1. 测试股票软件,模拟当天股票全部上涨
  2. 测试股票软件,模拟当天股票全部下跌
  3. 测试股票软件,模拟部分股票涨幅10%

Test Double 测试替身

  • Dummy 占位对象 对象被传递但从未实际使用过。通常它们仅用于填充参数列表。
  • Fake 假对象 对象实际上有工作实现,但通常采取一些捷径,这使得它们不适合生产(内存数据库就是一个很好的例子)。
  • Stubs 桩对象 为测试期间调用提供预设答案,通常根本不响应任何超出测试程序的内容。
  • Spies 间谍对象 它们还根据调用方式记录一些信息。其中一种形式可能是电子邮件服务,它记录发送了多少消息。
  • Mocks 模拟对象 是我们在这里谈论的:预先编程的对象,这些期望形成了它们期望接收的调用的规范。

测试替身关键概念的区别

image.png

一个真实的技术架构例子

  • dummy 只要端口开着就行
  • fake 内存数据库
  • spy UI 界面后端请求记录
  • stub 假的登录后端服务
  • hook 新用户判断方法修改
  • proxy 代理转发机制
  • mock 模拟对象

image.png

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).

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

image.png

Fake 应⽤场景

image.png

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.

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

image.png

Stub 应⽤场景 Swagger

image.png

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"
    }
}

image.png

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.

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

image.png

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.

image.png

mitmproxy mock on proxy

python3 -m http.server
mitmdump -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

image.png

#

adb mock 案例



import sys

from mitmproxy import ctx
from mitmproxy import tcp
from mitmproxy.utils import strutils
from 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.

image.png

wiremock stub

java -jar wiremock-jre8-standalone-2.33.2.jar
{
   
     "request": {
   
       "method": "GET",    "url": "/wiremock"  },
  "response": {
   
       "status": 200,    "body": "Easy!"  }}

mock on stub


@Test
public 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 的常见应用场景
相关文章
|
IDE Java 测试技术
Mockito 应用指南
Mockito 是一个针对 Java 的 mock 框架。
342 0
|
JavaScript
JS自动生成速记符、拼音简写/拼音的声母(例如:“你挚爱的强哥”转换为“NZADQG”)。提取首字母,返回大写形式;提取拼音, 返回首字母大写形式(全拼)。
JS自动生成速记符、拼音简写/拼音的声母(例如:“你挚爱的强哥”转换为“NZADQG”)。提取首字母,返回大写形式;提取拼音, 返回首字母大写形式(全拼)。
25567 0
|
Web App开发 JavaScript 前端开发
Vue2:基础入门
Vue2:基础入门
461 0
|
关系型数据库 TensorFlow 算法框架/工具
Docker技术概论(4):Docker CLI 基本用法解析
Docker技术概论(4):Docker CLI 基本用法解析
1231 1
|
Dubbo 应用服务中间件 API
什么是API网关
什么是API网关
|
人工智能 数据可视化 vr&ar
TripoSR:一个图像到3D生成模型,你get到了嘛!
TripoSR:一个图像到3D生成模型,你get到了嘛!
666 1
|
NoSQL 应用服务中间件 数据安全/隐私保护
Docker镜像创建及管理(Hub官方仓库使用及私有注册中心搭建)
Docker镜像创建及管理(Hub官方仓库使用及私有注册中心搭建)
|
安全
深入理解Qt多线程编程:QThread、QTimer与QAudioOutput的内在联系__Qt 事件循环(三)
深入理解Qt多线程编程:QThread、QTimer与QAudioOutput的内在联系__Qt 事件循环
506 0
|
Rust JavaScript 前端开发
【Neovim】配置美化完整流程
【Neovim】配置美化完整流程
8196 0
【Neovim】配置美化完整流程