成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go項目實戰-代碼里有API調用時單元測試怎么做?

開發 前端
觀察 CreateOrderPay 中的代碼我們發現,方法中除了對微信支付API的請求外 getToken、genPayInvokeInfo 這兩個 WxPayLib 中定義的私有方法分別做了拿微信支付請求Token 和生成前端喚起微信客戶端進行支付的參數的工作。

與數據庫的CURD操作類似,當我們對包含API接口調用的代碼進行單元測試時,肯定也是希望即不用對接口發起真正的網絡請求調用,也能驗證我們的API對接程序是否符合預期。那么今天我們就聚焦于怎么為與API對接程序做單元測試,本節大綱如下:

圖片圖片

在開發項目的過程中總會遇到要調用依賴方接口的情況,如果依賴方的API接口還沒有開發好,通常我們會先約定好API接口的請求參數、響應結構和各類錯誤對應的響應碼。這時雙方再按照這個約定同步進行開發。

除了上面說的情況外,還有一種就是當你開發的功能需要與微信支付類的API進行對接時,因為各種訂單、簽名、證書等的限制你在開發階段也不能直接去調用支付的API來驗證自己開發的程序是否能成功完成對接,這種時候我們該怎么辦呢?很多人會說發到測試環境讓QA造單子測,很多公司里的項目也確實是這么干的。

針對上面說的這些情況,我們有沒有什么辦法在開發階段就能通過單元測試來驗證我們寫的程序符不符合預期呢?這就需要我們掌握對API調用進行Mock的技巧了。

API 調用Mock 基礎

gock 是 Go 生態下一個提供無侵入 HTTP Mock 的工具,用來在單元測試中Mock API 的調用,即不對要請求的API發起真正的網絡調用,而是由gock攔截到請求后返回我們指定的Mock響應。

它支持用請求參數、請求頭、請求體等方式設置攔截請求的匹配條件,一旦匹配成功就會攔截測試程序中對API的調用,返回我們提前預設好的響應。

gock 的安裝方法如下

go get -u github.com/h2non/gock

關于 gock 的基本使用方法,可以參考我寫的這篇文章:用gock 攔截HTTP請求,Mock API調用 。我們接下來直接進入API Mock的實戰環節。

API Mock 測試實戰

我們項目的API對接都放在了API對接層 library 中,實戰環節中我挑選了兩個API對接邏輯演示如何對他們進行Mock單元測試,它們正好能覆蓋了GET、POST兩種請求方式下按照請求參數匹配攔截API請求和JSON請求體匹配攔截API請求。

單元測試入口TestMain的設置

我們項目里的對外API對接都放在library層中,按照上節課我們為項目做的的單元測試目錄規劃,它的單元測試_test.go 文件都應該放在test/library 目錄中。

.
|---test
|     |---controller    # controller 的測試用例
|     |---dao    # dao 的測試用例
|     |---domainservice # 邏輯層領域服務的測試用例
|     |---library # 外部API對接的測試用例

在開始寫單元測試前我們還是需要在TestMain方法中做一些 library 包中單元測試的初始化基礎工作。

func TestMain(m *testing.M) {
 client := &http.Client{Transport: &http.Transport{}}
 gock.InterceptClient(client)
 // 把框架的httptool使用的http client 換成gock攔截的client
 httptool.SetUTHttpClient(client)
 os.Exit(m.Run())
}

因為我們項目中的API調用都是httptool來發起的,所以我們需要把 httptool持有的全局httpClient 替換成由 gock 做了攔截的httpClient,只有這樣才能為項目中library層中封裝的各個API對接程序做攔截和Mock。

實戰案例一:IP地址查詢的Mock測試

實戰環節先來一個簡單點的案例,在library中我們曾經演示過一個用 whois API 查詢本機IP詳情的程序,具體程序如下:

func (whois *WhoisLib) GetHostIpDetail() (*WhoisIpDetail, error) {
 log := logger.New(whois.ctx)

 httpStatusCode, respBody, err := httptool.Get(
  whois.ctx, "https://ipwho.is",
  httptool.WithHeaders(map[string]string{
   "User-Agent": "curl/7.77.0",
  }),
 )
if err != nil {
  log.Error("whois request error", "err", err, "httpStatusCode", httpStatusCode)
returnnil, err
 }
 reply := new(WhoisIpDetail)
 json.Unmarshal(respBody, reply)

return reply, nil
}

里面的邏輯很簡單,只有一個簡單的對whois API 的GET方式的請求調用,我們對 WhoisLib 的GetHostIpDetail 方法做單測時,可以對whois的API做Mock,讓API返回我們指定的IP地址,然后讓測試程序驗證 GetHostIpDetail 方法返回的是不是這個指定的IP地址。

具體的單元測試方法如下:

func TestWhoisLib_GetHostIpDetail(t *testing.T) {
 defer gock.Off()
 gock.New("https://ipwho.is").
  MatchHeader("User-Agent", "curl/7.77.0").Get("").
  Reply(200).
  BodyString("{\"ip\":\"127.126.113.220\",\"success\":true}")

 ipDetail, err := library.NewWhoisLib(context.TODO()).GetHostIpDetail()
 assert.Nil(t, err)
 assert.Equal(t, "127.126.113.220", ipDetail.Ip)
}

你可能會說這個例子也太簡單了,別著急,接下來我們來個難的。

實戰案例二:微信支付的Mock測試

當在開發的功能需要與微信支付類的API進行對接時,因為各種訂單、簽名、證書等的限制,在開發階段不能直接去調用支付的API來驗證自己開發的程序是否能成功完成對接,在這種情況下如果能掌握API Mock技巧,能讓我們提前做好自己開發程序的邏輯驗證。

我們拿項目 WxPayLib 中的 CreateOrderPay 方法來給大家舉例子,這個方法會根據訂單數據向微信支付的JSAPI發起支付預下單,拿到預下單ID后再生成前端喚起微信進行支付所需要的信息返給前端。

CreateOrderPay 方法的實現如下:

func (wpl *WxPayLib) CreateOrderPay(order *do.Order, userOpenId string) (payInvokeInfo *WxPayInvokeInfo, err error) {
// 創建預支付單
// 微信支付文檔:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
 payDescription := fmt.Sprintf("GOMALL 商場購買%s 等商品", order.Items[0].CommodityName)
 prePayPram := &PrePayParam{
  AppId:       wpl.payConfig.AppId,
  MchId:       wpl.payConfig.MchId,
  Description: payDescription,
  OutTradeNo:  order.OrderNo,
  NotifyUrl:   wpl.payConfig.NotifyUrl,
 }
 prePayPram.Amount.Total = order.PayMoney
 prePayPram.Amount.Currency = "CNY"
 prePayPram.Payer.OpenId = userOpenId
 reqBody, _ := json.Marshal(prePayPram)
 token, err := wpl.getToken(http.MethodPost, string(reqBody), prePayApiUrl)
if err != nil {
  err = errcode.Wrap("WxPayLibCreatePrePayError", err)
return
 }
 _, replyBody, err := httptool.Post(wpl.ctx, prePayApiUrl, reqBody, httptool.WithHeaders(map[string]string{
"Authorization": "WECHATPAY2-SHA256-RSA2048 " + token,
 }))
if err != nil {
  err = errcode.Wrap("WxPayLibCreatePrePayError", err)
return
 }
 prepayReply := struct {
  PrePayId string`json:"prepay_id"`
 }{}
if err = json.Unmarshal(replyBody, &prepayReply); err != nil {
  err = errcode.Wrap("WxPayLibCreatePrePayError", err)
return
 }
// 生成前端調起支付需要的參數
 payInvokeInfo, err = wpl.genPayInvokeInfo(prepayReply.PrePayId)
if err != nil {
  err = errcode.Wrap("WxPayLibCreatePrePayError", err)
 }
return payInvokeInfo, nil
}

觀察 CreateOrderPay 中的代碼我們發現,方法中除了對微信支付API的請求外 getToken、genPayInvokeInfo 這兩個 WxPayLib 中定義的私有方法分別做了拿微信支付請求Token 和生成前端喚起微信客戶端進行支付的參數的工作。

那么想要對 CreateOrderPay 進行單元測試除了Mock方法中對微信支付預下單接口的API請求外,還需要Mock 依賴的getToken和genPayInvokeInfo兩個方法的返回,而且因為它們兩個是私有方法,在test目錄Mock 它們就必須使用支持 Mock 私有方法的工具,好在Go的生態夠全,這里我使用的是gomonkey這個庫。

完成這個測試程序中主要分三步

  • 造Order訂單數據。
  • 為WxPayLib的genToken方法打樁,指定我們期望的返回。
  • 使用 gock Mock 對 https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi 的調用。
  • 為WxPayLib的genPayInvokeInfo方法打樁,指定我們期望的返回。
  • 用 assert 斷言各種結果,決定單元測試是否成功。
責任編輯:武曉燕 來源: 網管叨bi叨
相關推薦

2022-05-09 08:55:52

ORMMockGo

2025-04-28 01:55:00

工具sqlmockSQL

2021-09-18 15:40:03

Vue單元測試命令

2022-04-08 09:01:56

腳本Go應用單元

2012-05-17 09:09:05

Titanium單元測試

2025-02-06 08:54:45

gockGoHTTP

2017-01-14 23:42:49

單元測試框架軟件測試

2022-08-02 08:07:24

單元測試代碼重構

2014-02-25 10:25:52

單元測試測試

2019-12-18 10:25:12

機器學習單元測試神經網絡

2024-01-09 08:08:12

Go單元測試系統

2021-05-17 05:51:31

KubeBuilderOperator測試

2009-06-26 17:48:38

JSF項目單元測試JSFUnit

2011-07-27 17:02:12

Xcode iPhone 單元測試

2017-01-14 23:26:17

單元測試JUnit測試

2017-01-16 12:12:29

單元測試JUnit

2020-08-18 08:10:02

單元測試Java

2016-09-21 10:18:26

阿里Dubbo性能測試

2021-05-05 11:38:40

TestNGPowerMock單元測試

2017-03-23 16:02:10

Mock技術單元測試
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品日韩一区 | 精品亚洲一区二区三区 | 国产一区二区在线看 | 99re在线观看| 99国产精品久久久 | 99久久久久久99国产精品免 | 中文字幕视频在线观看 | 黄色亚洲网站 | 久久久久久久久久久久久久国产 | 日韩欧美在线播放 | 欧美激情视频一区二区三区在线播放 | 一区2区 | 91色综合| 99精品一区 | 亚洲成人一区二区 | 欧美精品成人一区二区三区四区 | 欧美二区三区 | 毛片一区二区 | 91精品久久久久久久久 | 午夜爱爱毛片xxxx视频免费看 | 涩涩视频在线观看 | 国内自拍视频在线观看 | 拍真实国产伦偷精品 | 在线播放一区二区三区 | 热99在线| 国产一区精品 | 天天拍天天操 | 伊人免费网 | 成人av一区二区三区 | 欧美激情久久久 | 午夜久久av | 日韩高清一区二区 | 日韩欧美一区二区三区在线播放 | 伊人超碰 | 精品国产一区二区三区久久久久久 | 国精产品一区二区三区 | 五月香婷婷 | 午夜男人免费视频 | 青青草在线播放 | 久久精品影视 | 国产视频一区二区在线观看 |