偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Go項(xiàng)目里的API對(duì)接,這樣做Mock測(cè)試才舒服

開發(fā) 前端
gock 是 Go 生態(tài)下一個(gè)提供無侵入 HTTP Mock 的工具,用來在單元測(cè)試中Mock API 的調(diào)用,即不對(duì)要請(qǐng)求的API發(fā)起真正的調(diào)用,而是由gock攔截到請(qǐng)求后返回我們指定的Mock響應(yīng)。

我們?cè)陂_發(fā)項(xiàng)目的過程中總會(huì)遇到要調(diào)用依賴方接口的情況,如果依賴方的API接口還沒有開發(fā)好,通常我們會(huì)先約定好API接口的請(qǐng)求參數(shù)、響應(yīng)結(jié)構(gòu)和各類錯(cuò)誤對(duì)應(yīng)的響應(yīng)碼,再按照約定好請(qǐng)求和響應(yīng)進(jìn)行開發(fā)。

除了上面說的情況外,還有一種就是當(dāng)你開發(fā)的功能需要與微信支付類的API進(jìn)行對(duì)接時(shí),因?yàn)楦鞣N訂單、簽名、證書等的限制你在開發(fā)階段也不能直接去調(diào)用支付的API來驗(yàn)證自己開發(fā)的程序是否能成功完成對(duì)接,這種時(shí)候我們?cè)撛趺崔k呢?很多人會(huì)說發(fā)到測(cè)試環(huán)節(jié)讓QA造單子測(cè),很多公司里的項(xiàng)目也確實(shí)是這么干的。

針對(duì)上面說的兩種情況,我們有沒有什么辦法在開發(fā)階段就能通過單元測(cè)試來驗(yàn)證我們寫的程序符不符合預(yù)期呢?這就需要我們掌握對(duì)API調(diào)用進(jìn)行Mock的技巧了。

gock

gock 是 Go 生態(tài)下一個(gè)提供無侵入 HTTP Mock 的工具,用來在單元測(cè)試中Mock API 的調(diào)用,即不對(duì)要請(qǐng)求的API發(fā)起真正的調(diào)用,而是由gock攔截到請(qǐng)求后返回我們指定的Mock響應(yīng)。

它是如何模擬的

  • 用 http.DefaultTransport或自定義http.Transport攔截的任何 HTTP 請(qǐng)求流量
  • 將傳出的 HTTP 請(qǐng)求與按 FIFO 聲明順序定義的 HTTP 模擬期望池匹配。
  • 如果至少有一個(gè)模擬匹配,它將被用來組成模擬 HTTP 響應(yīng)。
  • 如果沒有匹配到的mock,則解析請(qǐng)求報(bào)錯(cuò),除非啟用了真實(shí)網(wǎng)絡(luò)模式,在這種情況下,將執(zhí)行真實(shí)的HTTP請(qǐng)求。

gock 的安裝方法

gock 的安裝方法如下

go get -u github.com/h2non/gock

gock 在官方的Github中給出了一些使用例子

  • 官方GitHub:https://github.com/h2non/gock
  • 官方給出的例子:https://github.com/h2non/gock/tree/master/_examples

這里我找一些典型常用的案例分享給大家,也說一下我在使用后對(duì)它們的理解,讓大家能更容易上手。

gock 的使用案例

匹配請(qǐng)求頭,對(duì)匹配到的請(qǐng)求進(jìn)行Mock。

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

  gock.New("http://foo.com").
    MatchHeader("Authorization", "^foo bar$").
    MatchHeader("API", "1.[0-9]+").
    HeaderPresent("Accept").
    Reply(200).
    BodyString("foo foo")

  req, err := http.NewRequest("GET", "http://foo.com", nil)
  req.Header.Set("Authorization", "foo bar")
  req.Header.Set("API", "1.0")
  req.Header.Set("Accept", "text/plain")

  res, err := (&http.Client{}).Do(req)
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 200)
  body, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(body), "foo foo")

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}

請(qǐng)求參數(shù)匹配,對(duì)匹配到的請(qǐng)求進(jìn)行Mock。

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

  gock.New("http://foo.com").
    MatchParam("page", "1").
    MatchParam("per_page", "10").
    Reply(200).
    BodyString("foo foo")

  req, err := http.NewRequest("GET", "http://foo.com?page=1&per_page=10", nil)

  res, err := (&http.Client{}).Do(req)
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 200)
  body, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(body), "foo foo")

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}

JSON 請(qǐng)求體匹配。

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

  gock.New("http://foo.com").
    Post("/bar").
    MatchType("json").
    JSON(map[string]string{"foo": "bar"}).
    Reply(201).
    JSON(map[string]string{"bar": "foo"})

  body := bytes.NewBuffer([]byte(`{"foo":"bar"}`))
  res, err := http.Post("http://foo.com/bar", "application/json", body)
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 201)

  resBody, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(resBody)[:13], `{"bar":"foo"}`)

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}

上面JSON的請(qǐng)求體要跟調(diào)用時(shí)發(fā)送的請(qǐng)求體完全一致,不然gock匹配不到這個(gè)請(qǐng)求, 如果匹配不上會(huì)報(bào)錯(cuò):gock: cannot match any request。

上面的這些案例都是用的Go http 的 default client,通常在項(xiàng)目里會(huì)自己封裝 http util 來簡化和標(biāo)準(zhǔn)化項(xiàng)目的API請(qǐng)求調(diào)用 ,這時(shí)候需要把 http util里的client 替換成經(jīng)過 gock.InterceptClient(client) 攔截的Client ,這樣用http util 發(fā)起的API請(qǐng)求才能gock 攔截到。

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

  gock.New("http://foo.com").
    Reply(200).
    BodyString("foo foo")

  req, err := http.NewRequest("GET", "http://foo.com", nil)
  client := &http.Client{Transport: &http.Transport{}}
  gock.InterceptClient(client)

  res, err := client.Do(req)
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 200)
  body, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(body), "foo foo")

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}

微信支付API對(duì)接怎么Mock測(cè)試

因?yàn)楦鞣N訂單、簽名、證書等的限制你在開發(fā)階段不能直接去調(diào)用支付的API來驗(yàn)證自己開發(fā)的程序是否能成功完成對(duì)接。

我在《Go項(xiàng)目搭建和整潔開發(fā)實(shí)戰(zhàn)》的單元測(cè)試實(shí)戰(zhàn)部分,給跟微信支付API對(duì)接的程序做了單元測(cè)試,除了使用到gock外,還用gomonkey mock了程序中用到的項(xiàng)目對(duì)接層的私有方法

func TestWxPayLib_CreateOrderPay(t *testing.T) {
 defer gock.Off()
 ......
 request := library.PrePayParam{
  AppId:       payConfig.AppId,
  MchId:       payConfig.MchId,
  OutTradeNo:  order.OrderNo,
  NotifyUrl:   payConfig.NotifyUrl,
  Amount: ...
  Payer: struct {
   OpenId string `json:"open_id"`
  }{OpenId: openId},
 }

 gock.New("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi").
  Post("").MatchType("json").
  JSON(request).
  Reply(200).
  JSON(map[string]string{"prepay_id": "wx26112221580621e9b071c00d9e093b0000"})

 wxPayLib := library.NewWxPayLib(context.TODO(), payConfig)
 var s *library.WxPayLib
 patchesOne := gomonkey.ApplyPrivateMethod(s, "getToken", func(_ *library.WxPayLib, httpMethod string, requestBody string, wxApiUrl string) (string, error) {
  token := fmt.Sprintf("mchid=\"%s\",nonce_str=\"%s\",timestamp=\"%d\",serial_no=\"%s\",signature=\"%s\"",
   payConfig.MchId, "abcddef", time.Now().Unix(), payConfig.PrivateSerialNo, "")
  return token, nil
 })
   ...

 payInfo, err := wxPayLib.CreateOrderPay(order, openId)
 assert.Nil(t, err)
 assert.Equal(t, "e61463f8efa94090b1f366cccfbbb444", payInfo.NonceStr)
 if payInfo.PaySign == "" || payInfo.Package == "" {
  t.Fail()
 }


責(zé)任編輯:武曉燕 來源: 網(wǎng)管叨bi叨
相關(guān)推薦

2025-05-07 09:06:03

2022-12-12 08:53:53

Go版本方式

2017-07-27 16:18:18

開源項(xiàng)目使用

2020-05-15 15:28:51

爬蟲Python學(xué)習(xí)

2016-03-28 10:11:37

2023-10-28 10:10:41

2022-05-09 08:55:52

ORMMockGo

2020-10-25 19:58:04

Pythonic代碼語言

2015-05-19 14:41:22

2024-12-17 09:14:48

項(xiàng)目http 庫API

2024-07-29 12:12:59

2022-02-17 07:54:55

VSCodeLinux內(nèi)核

2021-10-17 23:46:06

Go項(xiàng)目版本號(hào)

2024-11-13 09:13:45

2021-02-07 11:43:03

數(shù)據(jù)分析項(xiàng)目

2021-02-05 11:36:42

數(shù)據(jù)業(yè)務(wù)指標(biāo)

2013-10-10 09:50:40

云計(jì)算H3C

2024-05-10 08:36:40

Go語言對(duì)象

2017-12-13 17:39:37

ERP信息化企業(yè)

2021-04-20 10:50:38

Spring Boot代碼Java
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)