




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年中金汇通信技术有限公司甘肃分公司招聘60人笔试参考题库附带答案详解
- 计划你的2024年纺织品检验员考试试题及答案
- 纺织品质量控制方法试题及答案
- 耳鼻喉科英文试题及答案
- 环保科技示范园建设项目可行性研究报告分析
- 解除《租赁合同》协议书
- 瓷粉施工合同协议书
- 建筑施工合同合同协议书
- 礼品供货合同协议书范本
- 拟定合同协议书
- 小学生中医药文化知识科普传承中医文化弘扬国粹精神课件
- 2024年福建省中考历史试卷(含标准答案及解析)
- 代持存款合同协议书
- 继子女断绝关系协议书
- 车辆维修免责协议书范本
- 国开《会计学概论》网核模拟测试答案
- 2023年度健康体检大数据蓝皮书-美年健康+中关村美年健康产业研究院
- DB32T3748-2020 35kV及以下客户端变电所建设标准
- ASME材料-设计许用应力
- 采用SF6N2混合气体绝缘的GIS母线和GIL应用导则
- 数字贸易学 课件 第15章 数字支付与数字货币
评论
0/150
提交评论