gin单元测试启动服务后测试controller接口

1、使用的包是 net/http/httptest 

2、单元测试需要启动 gin 服务,然后 httptest.NewRequest 发送请求

示例代码:

mkdir gin
cd gin
go mod init example.com
go get github.com/gin-gonic/gin
go get github.com/stretchr/testify

创建 web 控制器

cd gin
mkdir controller
touch user.go
touch user_test.go

其中 user.go 的内容

package controller

import (
    "fmt"
    "net/http"

    "github.com/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(&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
}

单元测试代码 user_test.go

package controller

import (
    "encoding/json"
    "net/http"
    "net/http/httptest"
    "strings"
    "testing"

    "github.com/stretchr/testify/assert"
)

type p struct {
    name   string
    param  string
    expect string
}

// go test -timeout 30s -run ^Test_helloHandler$ example.com/controller
func Test_helloHandler(t *testing.T) {
    // 定义两个测试用例
    tests := []p{
        {"base case", `{"name": "jack"}`, "hello jack"},
        {"bad case", "", "we need a name"},
    }
    r := SetupRouter()
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            // mock一个HTTP请求
            req := httptest.NewRequest("POST", "/hello", 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(w.Body.Bytes(), &resp)
            assert.Nil(t, err)
            assert.Equal(t, tt.expect, resp["msg"])
        })
    }
}

在controller所在的目录执行用例 (用 goland 和 vscode 都可以 , 用goland 可以很方便地看单元测试代码覆盖率)

cd controller
go test -timeout 30s -run ^Test_helloHandler$ example.com/controller

需要启动 gin 服务器相对比较麻烦

 

posted @ 2022-06-17 09:51  许伟强  阅读(575)  评论(0编辑  收藏  举报