当前位置:首页 > 文章列表 > Golang > Go教程 > Go Gock 怎样只模拟指定主机的 HTTP 请求

Go Gock 怎样只模拟指定主机的 HTTP 请求

来源:17golang原创 2026-10-29 11:09:45 0浏览 收藏

如果测试里只想替换一个上游 API,而不希望其他域名也被 mock,关键是把主机写进 Gock 的请求声明,并让测试代码使用明确的 HTTP 客户端。Gock 的拦截器按主机、方法和路径匹配;未匹配请求在默认严格模式下返回错误,不会悄悄访问真实服务。

官方地址:https://github.com/h2non/gock

要点速览
  • gock.New("https://api.example.test") 将 mock 范围落到目标主机。
  • 自定义客户端要先调用 gock.InterceptClient(client),默认客户端则使用全局拦截。
  • 测试结束用 gock.Off(),自定义客户端再配合 gock.RestoreClient(client)。

先把 mock 范围锁定到一个主机

Gock 的声明式 API 先接收基础 URL,再继续追加方法和路径。下面的 mock 只接受 api.example.test 的 GET /v1/items,同一个客户端访问其他主机时不会命中这条声明。

package main

import (
    "fmt"
    "io"
    "net/http"

    "github.com/h2non/gock"
)

func main() {
    // 结束时清空 mock,避免影响同一进程中的后续测试。
    defer gock.Off()

    // 关闭主机正则解释,让示例域名按字面量参与匹配。
    gock.New("https://api.example.test").
        WithOptions(gock.Options{DisableRegexpHost: true}).
        Get("/v1/items").
        Reply(200).
        JSON(map[string]any{"items": []string{"go", "http"}})

    // 该请求的主机和路径都满足 mock 声明。
    resp, err := http.Get("https://api.example.test/v1/items")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close() // 读取后释放响应体。

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }
    fmt.Println(resp.StatusCode, string(body))
}

这里的主机是第一层筛选条件,路径是第二层筛选条件。即使把路径改成 /v1/users,也不会误用这条 /v1/items mock。DisableRegexpHost 适合希望域名按普通字符串匹配的场景;如果确实需要一组子域名,再考虑保留默认的正则主机匹配。

Go Gock 指定 api.example.test 主机经过 Host matcher 和 Path matcher 返回 mock response 的结构说明图
图1:Gock 指定主机匹配链路说明图,不是截图或运行证据。

自定义 http.Client 要显式接管

如果业务代码没有使用 http.DefaultClient,仅注册 mock 还不够。应在发送请求前对目标客户端调用一次 gock.InterceptClient,并让客户端保留自己的 Transport。

client := &http.Client{Transport: &http.Transport{}}

// 只把这个客户端交给 Gock,其他客户端不受本段测试影响。
gock.InterceptClient(client)

req, err := http.NewRequest(http.MethodGet, "https://api.example.test/v1/items", nil)
if err != nil {
    panic(err) // 请求地址构造失败时直接结束测试。
}
resp, err := client.Do(req)
if err != nil {
    panic(err) // 未匹配或传输失败都应让测试显式失败。
}
defer resp.Body.Close() // 自定义客户端也要关闭响应体。

默认客户端和自定义客户端的差别在“拦截入口”,不在主机匹配规则。官方文档建议同一个 http.Client 只拦截一次;多次包装会让清理和 Transport 关系变得难以追踪。

用 IsDone 判断目标请求是否真的命中

状态码为 200 只能说明拿到了响应,还应检查 mock 是否已经被消费。一次性 mock 可以用 gock.IsDone() 判断;如果它仍为 false,通常意味着主机、方法、路径或请求次数没有对上。

现象优先检查处理方向
返回未匹配错误scheme、host、path、method逐项对照 mock 声明
IsDone 为 false请求没有发送或次数不符检查请求流程与 Times/Persist
其他域名也被替换是否写了过宽的主机正则使用字面量主机或收窄表达式

严格拦截、真实网络和清理怎么选

默认模式更适合单元测试:只要请求不匹配,测试立即得到错误,能尽早发现上游地址被改错。若要让未匹配主机继续访问真实网络,可显式调用 gock.EnableNetworking(),但这会让测试依赖外部服务,应该只用于有意设计的集成场景。

// 测试完成后关闭 Gock 的拦截和真实联网开关。
defer gock.Off()
defer gock.RestoreClient(client)

// 只在明确需要“未匹配请求走真实网络”时开启。
gock.EnableNetworking()

更稳妥的做法是每个测试声明自己的目标主机、尽量使用独立客户端,并把清理写成 defer。这样即使中途断言失败,也不会把拦截器遗留给后续用例。

Go Gock 目标主机命中 mock、其他主机进入未匹配错误并在测试结束执行 Off 与 RestoreClient 的边界说明图
图2:目标主机、其他主机与清理动作的边界说明图,不是截图或运行证据。

常见问题

为什么写了 gock.New 仍然访问真实网络?

常见原因是自定义客户端没有调用 InterceptClient,或者实际请求的 scheme、主机、路径与声明不同。先关闭真实联网,再根据未匹配错误逐项比对。

主机名里的点号需要转义吗?

默认主机匹配支持正则语义;不需要正则时使用 DisableRegexpHost: true,可以把域名按字面量处理,减少点号等字符带来的误匹配。

什么时候使用 Persist?

同一 mock 需要被多次请求消费时才使用 Persist();单元测试通常更适合一次性声明,并用 IsDone() 检查调用次数。

因此,“只模拟指定主机”的最小组合就是:把主机写入 gock.New,为自定义客户端显式安装拦截器,默认保持严格未匹配策略,最后用 Off 和 RestoreClient 清理。主机范围收窄后,再按需要增加路径、请求头或参数匹配。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go Testify 怎样用 InOrder 表达模拟调用先后关系Go Testify 怎样用 InOrder 表达模拟调用先后关系
上一篇
Go Testify 怎样用 InOrder 表达模拟调用先后关系
Go Testify 怎样在 Run 回调中修改指针参数
下一篇
Go Testify 怎样在 Run 回调中修改指针参数
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    773次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    770次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    852次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    821次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    651次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码