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

Go項目實戰(zhàn)-代碼里有API調(diào)用時單元測試怎么做?

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

與數(shù)據(jù)庫的CURD操作類似,當(dāng)我們對包含API接口調(diào)用的代碼進(jìn)行單元測試時,肯定也是希望即不用對接口發(fā)起真正的網(wǎng)絡(luò)請求調(diào)用,也能驗證我們的API對接程序是否符合預(yù)期。那么今天我們就聚焦于怎么為與API對接程序做單元測試,本節(jié)大綱如下:

圖片圖片

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

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

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

API 調(diào)用Mock 基礎(chǔ)

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

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

gock 的安裝方法如下

go get -u github.com/h2non/gock

關(guān)于 gock 的基本使用方法,可以參考我寫的這篇文章:用gock 攔截HTTP請求,Mock API調(diào)用 。我們接下來直接進(jìn)入API Mock的實戰(zhàn)環(huán)節(jié)。

API Mock 測試實戰(zhàn)

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

單元測試入口TestMain的設(shè)置

我們項目里的對外API對接都放在library層中,按照上節(jié)課我們?yōu)轫椖孔龅牡膯卧獪y試目錄規(guī)劃,它的單元測試_test.go 文件都應(yīng)該放在test/library 目錄中。

.
|---test
|     |---controller    # controller 的測試用例
|     |---dao    # dao 的測試用例
|     |---domainservice # 邏輯層領(lǐng)域服務(wù)的測試用例
|     |---library # 外部API對接的測試用例

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

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調(diào)用都是httptool來發(fā)起的,所以我們需要把 httptool持有的全局httpClient 替換成由 gock 做了攔截的httpClient,只有這樣才能為項目中l(wèi)ibrary層中封裝的各個API對接程序做攔截和Mock。

實戰(zhàn)案例一:IP地址查詢的Mock測試

實戰(zhàn)環(huán)節(jié)先來一個簡單點的案例,在library中我們曾經(jīng)演示過一個用 whois API 查詢本機(jī)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方式的請求調(diào)用,我們對 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)
}

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

實戰(zhàn)案例二:微信支付的Mock測試

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

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

CreateOrderPay 方法的實現(xiàn)如下:

func (wpl *WxPayLib) CreateOrderPay(order *do.Order, userOpenId string) (payInvokeInfo *WxPayInvokeInfo, err error) {
// 創(chuàng)建預(yù)支付單
// 微信支付文檔: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
 }
// 生成前端調(diào)起支付需要的參數(shù)
 payInvokeInfo, err = wpl.genPayInvokeInfo(prepayReply.PrePayId)
if err != nil {
  err = errcode.Wrap("WxPayLibCreatePrePayError", err)
 }
return payInvokeInfo, nil
}

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

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

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

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

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應(yīng)用單元

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

單元測試代碼重構(gòu)

2014-02-25 10:25:52

單元測試測試

2019-12-18 10:25:12

機(jī)器學(xué)習(xí)單元測試神經(jīng)網(wǎng)絡(luò)

2024-01-09 08:08:12

Go單元測試系統(tǒng)

2025-08-28 01:00:00

Go單元測試

2011-07-27 17:02:12

Xcode iPhone 單元測試

2009-06-26 17:48:38

JSF項目單元測試JSFUnit

2017-01-16 12:12:29

單元測試JUnit

2017-01-14 23:26:17

單元測試JUnit測試

2021-05-17 05:51:31

KubeBuilderOperator測試

2020-08-18 08:10:02

單元測試Java

2016-09-21 10:18:26

阿里Dubbo性能測試

2017-03-23 16:02:10

Mock技術(shù)單元測試
點贊
收藏

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