ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Mock技术的深度理解及Wire Mock框架基础使用

2021-12-08 18:32:05  阅读:204  来源: 互联网

标签:wiremock Wire tomakehurst 框架 github import com port Mock


一、关键概念

  1. spy:监听调用过程,不具备转发能力,主要是监听调用过程(类似抓包,F12的功能)
  2. stub:返回固定值的实现,无法在测试中进行动态变更(指无法根据真实的值进行动态变更),比较死板(类似Charles的map local功能,不经过后端,类似挡板)
  3. proxy:使用代理协议转发请求并返回真实内容,可以转发、监听,甚至修改(类似Charles的rewrite功能,把请求转发给真实的服务,服务返回response后,对response进行一些修改后转发给前端)
  4. fake:用假的实现代替真的实现,但是实现中做了些捷径(比如一个大集群下某个服务出故障,需要很长时间去修复,这个时候可以写一个简版的逻辑进行替代,通常是开发做的)
  5. mock:由mock库动态创建的,能提供类似spy、stub、proxy的功能。mock是一种特殊的fake,强调的是可控
  • mock on stub:直接返回固定值数据
  • mock on proxy:利用代理转发并修改返回数据

在这里插入图片描述

二、应用场景

一、stub应用场景:

  • Moco:https://github.com/dreamhead/moco
  • 轻量级stub框架,用命令行进行启动,方便在服务端操作

二、fake应用场景:

  • H2 Database Engine:轻量级的内存Sql,不会占用资源,是JDBC的api,操作方式和mysql之类的一致。如果是试运行阶段或者重点关注重点不在db层,可以使用这个框架。

三、mock应用场景:

  • Wire Mock:目前一款较为流行的mock框架,社区很活跃,写法也很优雅,功能和Charles差不多,但是更灵活,因为可以进行编码
  • 官网:http://wiremock.org/
  • 下面我们重点介绍下这款框架的基础配置和使用

1. 引入依赖

  <groupId>org.example</groupId>
    <artifactId>wiremock_demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-runner</artifactId>
            <version>1.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <version>1.7.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-console-standalone</artifactId>
            <version>1.7.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.github.tomakehurst</groupId>
            <artifactId>wiremock-jre8</artifactId>
            <version>2.31.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>net.lightbody.bmp</groupId>
            <artifactId>browsermob-core</artifactId>
            <version>2.1.5</version>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>4.4.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M5</version>
                <configuration>
                    <includes>
                        <include>**</include>
                    </includes>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>3.0.0-M5</version>
            </plugin>
        </plugins>
    </build>

2. 基础demo

import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer;
import org.junit.jupiter.api.Test;

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;

public class Demo_01_Base {
    @Test
    public void start() {
        int port = 8089;
        // 实例化wirmockServer对象
        WireMockServer wireMockServer = new WireMockServer(
                wireMockConfig()
                        // 配置端口号
                        .port(port)
                        // 配置全局response模板
                        .extensions(new ResponseTemplateTransformer(true))
        );
        // 启动mock服务
        wireMockServer.start();
        // 这边需要再次设置一下端口号,否则会报错
        configureFor(port);
        // 配置mock服务中的一个stub,类似Charles的mapLocal功能
        stubFor(get(urlEqualTo("/some/thing"))
                // 配置返回的body,header,statusCode
                .willReturn(
                        aResponse()
                                .withStatus(200)
                                .withHeader("content-Type", "application/json")
                                .withBody("this is my first wiremock demo!")
                ));
        System.out.println("http://localhost:" + port);
        // 等待10s,如果不等待就会直接停止服务,就启动不了了
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // wiremock复位
        WireMock.reset();
        // wiremock停止(不停止下一次就无法进行调用了)
        wireMockServer.stop();
    }
}

3. 常用的请求体的配置

import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer;
import org.junit.jupiter.api.Test;

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;

public class Demo_02_RequestMatching {
    @Test
    public void start() {
        int port = 8090;
        // 实例化wirmockServer对象
        WireMockServer wireMockServer = new WireMockServer(
                wireMockConfig()
                        // 配置端口号
                        .port(port)
                        // 配置全局response模板
                        .extensions(new ResponseTemplateTransformer(true))
        );
        // 启动mock服务
        wireMockServer.start();
        // 这边需要再次设置一下端口号,否则会报错
        configureFor(port);
        /**
         *   配置mock服务中的一个stub,类似Charles的mapLocal功能
         *   这些配置是“且”的关系,必须全部满足,才能请求成功
         */

        // url的路径等于"everything"’
        stubFor(any(urlPathEqualTo("everything"))
                //通过header匹配规则
                .withHeader("Accept", containing("xml"))
                //通过cookie匹配规则
                .withCookie("session", matching(".*12345.*"))
                //通过QueryParam匹配规则
                .withQueryParam("search_term", equalTo("WireMock"))
                //通过withBasicAuth匹配规则
                .withBasicAuth("jeff@example.com", "jeffteenjefftyjeff")
                //通过RequestBody匹配规则
                .withRequestBody(matchingJsonPath("$.a", equalTo("1")))
                .willReturn(aResponse().withStatus(200)
                        .withHeader("Content-Type", "text/plain")
                        .withBody("pass!")));
        System.out.println("http://localhost:" + port);
        // 等待10s,如果不等待就会直接停止服务,就启动不了了
        try {
            Thread.sleep(100000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // wiremock复位
        WireMock.reset();
        // wiremock停止(不停止下一次就无法进行调用了)
        wireMockServer.stop();
    }
}


做个测试

public class Demo_02_Test_RequestMatching {
    @Test
    void testRequestMatching() {
        given().log().all()
                .auth().preemptive().basic("jeff@example.com", "jeffteenjefftyjeff")
                .header("Accept", "xml")
                .cookie("session", "123456")
                .body("{\"a\":1,\"b\":2}")
                .queryParam("search_term", "WireMock")
                .when()
                .post("http://localhost:8099/everything").
                then().log().all()
                .extract();
    }
}

请求成功!
在这里插入图片描述

  • 查看wireMock的管理后台:ip:port/__admin
    在这里插入图片描述
    4. 常用的响应体的配置
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer;
import org.junit.jupiter.api.Test;

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;

/**
 * 常用的响应的配置
 */
public class Demo_03_Response {
    @Test
    public void start() {
        int port = 8091;
        // 实例化wirmockServer对象
        WireMockServer wireMockServer = new WireMockServer(
                wireMockConfig()
                        .port(port)
                        .extensions(new ResponseTemplateTransformer(true))
        );
        // 启动mock服务
        wireMockServer.start();
        configureFor(port);
        stubFor(get(urlEqualTo("/some/thing"))
                // 配置返回的body,header,statusCode
                .willReturn(
                        aResponse()
                                .withStatus(200)
                                .withHeader("content-Type", "application/json")
                                .withBody("this is my first wiremock demo!")
                ));
        // ok()表示返回响应状态码为200
        stubFor(delete("/fine")
                .willReturn(ok()));
        // 返回响应状态码+body
        stubFor(get("/fineWithBody")
                .willReturn(ok("body")));
        // 返回响应体为json格式
        stubFor(get("/returnJson")
                .willReturn(okJson("{\"status\":\"success\"}")));
        // 进行请求重定向
        stubFor(get("/redirect")
                .willReturn(temporaryRedirect("/new/place")));
        // 未鉴权
        stubFor(get("/unauthorized")
                .willReturn(unauthorized()));
        // 配置响应状态码
        stubFor(get("/statusCode")
                .willReturn(status(418)));

        System.out.println("http://localhost:" + port);
        try {
            Thread.sleep(100000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // wiremock复位
        WireMock.reset();
        // wiremock停止(不停止下一次就无法进行调用了)
        wireMockServer.stop();
    }
}

5. 匹配优先级

/**
 * 优先级匹配:
 * 1,匹配优先级高的
 * 2,再按照url进行匹配
 */
public class Demo_04_Priority {
    @Test
    public void start() {
        int port = 8093;
        // 实例化wirmockServer对象
        WireMockServer wireMockServer = new WireMockServer(
                wireMockConfig()
                        .port(port)
                        .extensions(new ResponseTemplateTransformer(true))
        );
        // 启动mock服务
        wireMockServer.start();
        configureFor(port);
        // 匹配特定的
        stubFor(get(urlEqualTo("/some/thing")).atPriority(2)
                // 配置返回的body,header,statusCode
                .willReturn(
                        aResponse()
                                .withStatus(200)
                                .withHeader("content-Type", "application/json")
                                .withBody("this is my first wiremock demo!")
                ));
        // 使用正则进行通配
        stubFor(get(urlMatching("/some/.*")).atPriority(12)
                .willReturn(
                        aResponse()
                                .withStatus(401)
                                .withBody("match any")
                ));
        // 兜底逻辑
        stubFor(any(anyUrl()).atPriority(1)
                .willReturn(
                        aResponse()
                                .withStatus(402)
                                .withBody("no match")
                ));
        System.out.println("http://localhost:" + port);
        try {
            Thread.sleep(100000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // wiremock复位
        WireMock.reset();
        // wiremock停止(不停止下一次就无法进行调用了)
        wireMockServer.stop();
    }
}

6. 录制和回放

wireMock也提供界面,进行录制和回放,功能类似于Charles里面的save response

  • 具体操作:
  1. 输入网址:http://ip:port/__admin/recorder/

  2. 在这个界面输入你想要录制的网址,然后点击录制选项

  3. 新开一个页面,输入http://ip:port,会自动路由到你输入的网址,这个时候你可以在页面进行一些操作
    在这里插入图片描述

  4. 点击stop停止录制
    在这里插入图片描述
    这个时候你会在resources目录里面看到mapping文件,里面放着录制好的请求
    在这里插入图片描述

  5. 我们可以修改里面的内容
    在这里插入图片描述
    然后再进行重启,再去访问http://ip:port,即可mock成功
    在这里插入图片描述

  6. proxy:使用代理协议转发请求并返回真实内容

/**
 * 使用代理协议转发请求并返回真实内容
 */
public class Demo_05_Proxy {
    @Test
    public void start() {
        int port = 8021;
        // 实例化wirmockServer对象
        WireMockServer wireMockServer = new WireMockServer(
                wireMockConfig()
                        // 配置端口号
                        .port(port)
                        // 配置全局response模板
                        .extensions(new ResponseTemplateTransformer(true),
                                // 新建一个response的处理器
                                new ResponseTransformer() {
                                    // 对response里的文本进行替换
                                    @Override
                                    public Response transform(Request request, Response response, FileSource fileSource, Parameters parameters) {
                                        return Response.Builder.like(response)
                                                .body(response.getBodyAsString().replace("Other Utilities","My proxy Utilities"))
                                                .build();
                                    }

                                    @Override
                                    public String getName() {
                                        return "proxy demo";
                                    }
                                })
        );
        // 启动mock服务
        wireMockServer.start();
        configureFor(port);
        // 配置mock服务中的一个stub
        stubFor(get(urlMatching("/.*"))
                .willReturn(
                        aResponse()
                                // 设置代理
                                .proxiedFrom("https://httpbin.ceshiren.com")
                ));
        System.out.println("http://localhost:" + port);
        try {
            Thread.sleep(10000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // wiremock复位
        WireMock.reset();
        // wiremock停止(不停止下一次就无法进行调用了)
        wireMockServer.stop();
    }
}

启动以后,访问ip:port,修改成功!
在这里插入图片描述

标签:wiremock,Wire,tomakehurst,框架,github,import,com,port,Mock
来源: https://blog.csdn.net/qq_36792120/article/details/121770715

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有