如何对golang的gin框架中的handler做单元测试

[本文出自天外归云的博客园]

Golang gin路由函数测试模板:

package handler

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"

	"内部log库和mock库可以替换成外部log库和gomonkey库"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
)

func setup() {
	log.Info("setup started")
	defer log.Info("setup completed")
}

func teardown() {
	log.Info("teardown started")
	defer log.Info("teardown completed")
}

func TestMain(m *testing.M) {
	setup()
	code := m.Run()
	teardown()
	os.Exit(code)
}

// testHTTPResponse 是一个发起请求并测试其返回的辅助函数
// https://semaphoreci.com/community/tutorials/building-go-web-applications-and-microservices-using-gin
func testHTTPResponse(t *testing.T, r *gin.Engine, req *http.Request, f func(w *httptest.ResponseRecorder) bool) {
	// 创建一个response接收体
	w := httptest.NewRecorder()
	// 创建服务并请求
	r.ServeHTTP(w, req)
	if !f(w) {
		t.Fail()
	}
}

// newReq 创建请求
func newReq(method ReqMethod, reqURL string, params map[string]string) (*http.Request, error) {
	paramsBytes, err := json.Marshal(params)
	if err != nil {
		return nil, fmt.Errorf("error marshal json->%+v", err)
	}
	r, newReqErr := http.NewRequest(string(method), reqURL, bytes.NewBuffer(paramsBytes))
	if newReqErr != nil {
		return nil, fmt.Errorf("error %+v request %+v->%+v", method, reqURL, err)
	}
	return r, nil
}

// ReqMethod 请求方法
type ReqMethod string

// 常量
const (
	Get  ReqMethod = "GET"  // Get请求
	Post ReqMethod = "POST" // Post请求
)

func TestUploadProjectIconHandlerValid(t *testing.T) {
	reqURL := "some/router/url"
	// Mock
	mock := mocker.Create()
	defer mock.Reset()
	// 待测gin路由准备
	testGinRouter := gin.Default()
	testGinRouter.POST(reqURL, RouterFunction)
	// 定义测试用例参数
	type args struct {
		reqParams  map[string]string
		customStub func()
	}
	// 定义测试用例预期结果
	type want struct {
		code int
		msg  string
	}
	// 定义并初始化测试用例
	tests := []struct {
		name string
		args args
		want want
	}{...}
	// 遍历用例
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// 自定义stub过程
			tt.args.customStub()
			// 模拟请求
			testReq, err := newReq(Post, reqURL, tt.args.reqParams)
			assert.Nil(t, err)
			// 测试gin框架路由http请求
			testHTTPResponse(t, testGinRouter, testReq, func(w *httptest.ResponseRecorder) bool {
				log.Infof("%+v", w.Body.String())
				assert.Equal(t, tt.want.code, w.Code)
				assert.Equal(t, tt.want.msg, w.Body.String())
				return true
			})
			// 重置mock
			mock.Reset()
		})
	}
}

  

posted @ 2021-08-23 17:41  天外归云  阅读(145)  评论(0编辑  收藏  举报