Contents

Gock

Contents

Gock:

​ 开发项目的过程中总会遇到要调用依赖方接口的情况,如果依赖方的API接口还没有开发好,通常我们会先约定好API接口的请求参数、响应结构和各类错误对应的响应码,再按照约定好请求和响应进行开发。有些情况在开发阶段不能直接调用,因此就需要进行对依赖的api进行mock

gock 是 Go 生态下一个提供无侵入 HTTP Mock 的工具,用来在单元测试中Mock API 的调用,即不对要请求的API发起真正的调用,而是由gock拦截到请求后返回我们指定的Mock响应。

它是如何模拟的

  • 用 http.DefaultTransport或自定义http.Transport拦截的任何 HTTP 请求流量
  • 将传出的 HTTP 请求与按 FIFO 声明顺序定义的 HTTP 模拟期望池匹配。
  • 如果至少有一个模拟匹配,它将被用来组成模拟 HTTP 响应。
  • 如果没有匹配到的mock,则解析请求报错,除非启用了真实网络模式,在这种情况下,将执行真实的HTTP请求。
go get -u github.com/h2non/gock

示例

func TestHttpc(t *testing.T) {
	defer gock.Off()

	domain := "https://github.com"
	apiPath := "/get"

	apiURL := fmt.Sprintf("%v%v", domain, apiPath)

	// Mock 对 https://httpbin.rs/get 的 GET 请求
	gock.New(domain).
		Get(apiPath).
		Reply(200).
		JSON(map[string]interface{}{
			"mocked": true,
			"headers": map[string]string{
				"User-Agent": "gock",
			},
			"url": "https://github.com/get",
		})
	resp, err := http.Get(apiURL)
	if err != nil {
		return
	}
	dataB, _ := io.ReadAll(resp.Body)
	fmt.Println(string(dataB))
}

如果使用里自定义的http.Client,则需要替换Transport为gock.NewTransport()

func main() {
	// 启用 gock 拦截器
	defer gock.Off() // 测试结束后关闭拦截

	// Mock 对 https://httpbin.rs/get 的 GET 请求
	gock.New("https://httpbin.rs").
		Get("/get").
		Reply(200).
		JSON(map[string]interface{}{
			"mocked": true,
			"headers": map[string]string{
				"User-Agent": "gock",
			},
			"url": "https://httpbin.rs/get",
		})

	req.Client().Transport = gock.NewTransport()
	// 发起请求(会被 gock 拦截)
	resp, err := req.Get("https://httpbin.rs/get")
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	fmt.Printf("resp: %s\n", resp.String())
}

resty mock

func TestResty(t *testing.T) {
	defer gock.Off()

	domain := "https://github.com"
	apiPath := "/get"

	apiURL := fmt.Sprintf("%v%v", domain, apiPath)

	// Mock 对 https://httpbin.rs/get 的 GET 请求
	gock.New(domain).
		Get(apiPath).
		Reply(200).
		JSON(map[string]interface{}{
			"mocked": true,
			"headers": map[string]string{
				"User-Agent": "gock",
			},
			"url": "https://github.com/get",
		})
	req := resty.New().SetTransport(gock.NewTransport()).R()
	resp, err := req.Get(apiURL)
	if err != nil {
		return
	}
	fmt.Println(resp.String())
}