




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第Go語言單元測試模擬服務請求和接口返回目錄前言httptestgock安裝使用示例總結
前言
這是Go單元測試從入門到放棄系列教程的第1篇,介紹了如何使用httptest和gock工具進行網絡測試。
在上一篇《Go單元測試從入門到放棄0.單元測試基礎》中,我們介紹了Go語言編寫單元測試的基礎內容。
而實際工作中的業務場景往往會比較復雜,無論我們的代碼是作為server端對外提供服務或者還是我們依賴別人提供的網絡服務(調用別人提供的API接口)的場景,我們通常都不想在測試過程中真正的建立網絡連接。本文就專門介紹如何在上述兩種場景下mock網絡測試。
httptest
在Web開發場景下的單元測試,如果涉及到HTTP請求推薦大家使用Go標準庫net/http/httptest進行測試,能夠顯著提高測試效率。
在這一小節,我們以常見的gin框架為例,演示如何為httpserver編寫單元測試。
假設我們的業務邏輯是搭建一個httpserver端,對外提供HTTP服務。我們編寫了一個helloHandler函數,用來處理用戶請求。
//
gin.go
package
httptest_demo
import
(
"fmt"
"net/http"
"/gin-gonic/gin"
//
Param
請求參數
type
Param
struct
{
Name
string
`json:"name"`
//
helloHandler
/hello請求處理函數
func
helloHandler(c
*gin.Context)
{
var
p
Param
if
err
:=
c.ShouldBindJSON(amp;p);
err
!=
nil
{
c.JSON(http.StatusOK,
gin.H{
"msg":
"we
need
a
name",
return
c.JSON(http.StatusOK,
gin.H{
"msg":
fmt.Sprintf("hello
%s",
p.Name),
//
SetupRouter
路由
func
SetupRouter()
*gin.Engine
{
router
:=
gin.Default()
router.POST("/hello",
helloHandler)
return
router
現在我們需要為helloHandler函數編寫單元測試,這種情況下我們就可以使用httptest這個工具mock一個HTTP請求和響應記錄器,讓我們的server端接收并處理我們mock的HTTP請求,同時使用響應記錄器來記錄server端返回的響應內容。
單元測試的示例代碼如下:
//
gin_test.go
package
httptest_demo
import
(
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
"/stretchr/testify/assert"
func
Test_helloHandler(t
*testing.T)
{
//
定義兩個測試用例
tests
:=
[]struct
{
name
string
param
string
expect
string
{"base
case",
`{"name":
"liwenzhou"}`,
"hello
liwenzhou"},
{"bad
case",
"",
"we
need
a
name"},
r
:=
SetupRouter()
for
_,
tt
:=
range
tests
{
t.Run(,
func(t
*testing.T)
{
//
mock一個HTTP請求
req
:=
httptest.NewRequest(
"POST",
//
請求方法
"/hello",
//
請求URL
strings.NewReader(tt.param),
//
請求參數
//
mock一個響應記錄器
w
:=
httptest.NewRecorder()
//
讓server端處理mock請求并記錄返回的響應內容
r.ServeHTTP(w,
req)
//
校驗狀態碼是否符合預期
assert.Equal(t,
http.StatusOK,
w.Code)
//
解析并檢驗響應內容是否復合預期
var
resp
map[string]string
err
:=
json.Unmarshal([]byte(w.Body.String()),
amp;resp)
assert.Nil(t,
err)
assert.Equal(t,
tt.expect,
resp["msg"])
執行單元測試,查看測試結果
?gotest-v
===RUNTest_helloHandler
[GIN-debug][WARNING]CreatinganEngineinstancewiththeLoggerandRecoverymiddlewarealreadyattached.
[GIN-debug][WARNING]Runningindebugmode.Switchtoreleasemodeinproduction.
-usingenv:exportGIN_MODE=release
-usingcode:gin.SetMode(gin.ReleaseMode)
[GIN-debug]POST/hello--golang-unit-test-demo/httptest_demo.helloHandler(3handlers)
===RUNTest_helloHandler/base_case
[GIN]2025/09/14-22:00:04|200|164.839s||POST/hello
===RUNTest_helloHandler/bad_case
[GIN]2025/09/14-22:00:04|200|23.723s||POST/hello
---PASS:Test_helloHandler(0.00s)
---PASS:Test_helloHandler/base_case(0.00s)
---PASS:Test_helloHandler/bad_case(0.00s)
PASS
okgolang-unit-test-demo/httptest_demo0.055s
通過這個示例我們就掌握了如何使用httptest在HTTPServer服務中為請求處理函數編寫單元測試了。
gock
上面的示例介紹了如何在HTTPServer服務類場景下為請求處理函數編寫單元測試,那么如果我們是在代碼中請求外部API的場景(比如通過API調用其他服務獲取返回值)又該怎么編寫單元測試呢?
例如,我們有以下業務邏輯代碼,依賴外部API:/post提供的數據。
//
api.go
//
ReqParam
API請求參數
type
ReqParam
struct
{
X
int
`json:"x"`
//
Result
API返回結果
type
Result
struct
{
Value
int
`json:"value"`
func
GetResultByAPI(x,
y
int)
int
{
p
:=
amp;ReqParam{X:
x}
b,
_
:=
json.Marshal(p)
//
調用其他服務的API
resp,
err
:=
http.Post(
"/post",
"application/json",
bytes.NewBuffer(b),
if
err
!=
nil
{
return
-1
body,
_
:=
ioutil.ReadAll(resp.Body)
var
ret
Result
if
err
:=
json.Unmarshal(body,
amp;ret);
err
!=
nil
{
return
-1
//
這里是對API返回的數據做一些邏輯處理
return
ret.Value
+
y
在對類似上述這類業務代碼編寫單元測試的時候,如果不想在測試過程中真正去發送請求或者依賴的外部接口還沒有開發完成時,我們可以在單元測試中對依賴的API進行mock。
這里推薦使用gock這個庫。
安裝
go
get
-u
gopkg.in/h2non/gock.v1
使用示例
使用gock對外部API進行mock,即mock指定參數返回約定好的響應內容。下面的代碼中mock了兩組數據,組成了兩個測試用例。
//
api_test.go
package
gock_demo
import
(
"testing"
"/stretchr/testify/assert"
"gopkg.in/h2non/gock.v1"
func
TestGetResultByAPI(t
*testing.T)
{
defer
gock.Off()
//
測試執行后刷新掛起的mock
//
mock
請求外部api時傳參x=1返回100
gock.New("").
Post("/post").
MatchType("json").
JSON(map[string]int{"x":
1}).
Reply(200).
JSON(map[string]int{"value":
100})
//
調用我們的業務函數
res
:=
GetResultByAPI(1,
1)
//
校驗返回結果是否符合預期
assert.Equal(t,
res,
101)
//
mock
請求外部api時傳參x=2返回200
gock.New("").
Post("/post").
MatchType("json").
JSON(map[string]int{"x":
2}).
Reply(200).
JSON(map[string]int{"value":
200})
//
調用我們的業務函數
res
=
GetResultByAPI(2,
2)
//
校驗返回結果是否符合預期
assert.Equal(t,
res,
202)
assert.True(t,
gock.IsDone())
//
斷言mock被觸發
執行上面寫好的單元測試,看一下測試結果。
?gotest-v
===RUNTestGetResultByAPI
---PASS:TestGetResultByAPInbsp;(0.00s)
PASS
okgolang-unit-test-demo/gock_demo0.054s
測試結果和預期的完全一致。
在這個示例中,為了讓大家能夠清晰的了解gock的使用,我特意沒有使用表格驅動測試。給大家留一個小作業:自己動手把這個單元測試改寫成表格驅動測試的風
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 服裝店鋪協議書
- 月嫂定金協議書
- 軟件委托研發合同協議
- 通風排煙施工合同協議
- 輕鋼工程分包合同協議
- 永定征收協議書
- 車輛招商意向金合同協議
- 輪胎回收轉讓協議合同書
- 足浴轉讓合同協議書范本
- 民間居間協議書
- DB32T3748-2020 35kV及以下客戶端變電所建設標準
- ASME材料-設計許用應力
- 采用SF6N2混合氣體絕緣的GIS母線和GIL應用導則
- 數字貿易學 課件 第15章 數字支付與數字貨幣
- 中華民族共同體概論課件專家版6第六講 五胡入華與中華民族大交融(魏晉南北朝)
- 體外高頻熱療的護理
- JGJ79-2012 建筑地基處理技術規范
- ??低曅U性诰€測評題庫
- 新編酒水知識與調酒
- 采礦工程畢業設計(論文)-趙固二礦180萬ta新井設計
- XXX公司工程技術研究中心中心匯報
評論
0/150
提交評論