基于golang gin框架的单元测试 - Go语言中文社区

基于golang gin框架的单元测试


在用Gin框架编写了一个web server之后,我们如果需要测试handlers接口函数的话,主要可以采用两种方式来进行。

第一种是部署web server,然后通过浏览器或其他http请求模拟工具来手动模拟真实的http请求,发送http请求之后,解析返回的响应,查看响应是否符合预期;这种做法比较麻烦,而且测试结果不太可靠。

第二种是使用httptest结合testing来实现针对handlers接口函数的单元测试。

github项目地址:https://github.com/Valiben/gin_unit_test

下面以一个简单的登录handler为例子,来说明基于Gin框架的单元测试的方法。

首先定义接口处理函数:

type User struct {
   Username string `form:"username" json:"username" binding:"required"`
   Password   string `form:"password" json:"password" binding:"required"`
   Age int `form:"age" json:"age" binding:"required"`
}

func LoginHandler(c *gin.Context) {
   req := &User{}
   if err := c.Bind(req); err != nil {
      log.Printf("err:%v", err)
      c.JSON(http.StatusOK, gin.H{
         "errno":  "1",
         "errmsg": "parameters not match",
      })
      return
   }

   // judge the password and username
   if req.UserName != "Valiben" || req.Password != "123456" {
      c.JSON(http.StatusOK, gin.H{
         "errno":  "2",
         "errmsg": "password or username is wrong",
      })
      return
   }

   c.JSON(http.StatusOK, gin.H{
      "errno":  "0",
      "errmsg": "login success",
   })
}

接下来,在单元测试文件中导入上述包:

import utils "github.com/Valiben/gin_unit_test"

搭建路由,将engine设置到utils中:

router := gin.Default()
router.POST("/login", LoginHandler)
utils.SetRouter(router)

设置好engine之后你就可以像下面一样编写一个单元测试用例来测试登录接口了:

type OrdinaryResponse struct {
   Errno  string `json:"errno"`
   Errmsg string `json:"errmsg"`
}

func TestLoginHandler(t *testing.T) {
   resp := OrdinaryResponse{}
   
   err := utils.TestHandlerUnMarshalResp(utils.POST, "/login", utils.Form, user, &resp)
   if err != nil {
      t.Errorf("TestLoginHandler: %vn", err)
      return
   }
   
   if resp.Errno != "0" {
      t.Errorf("TestLoginHandler: response is not expectedn")
      return
   }
}

然后就可以运行这个单元测试来检验接口函数啦,是不是很简单呢。

如果是上传文件之类的接口的单元测试,怎么来写呢,假设上传文件的接口函数如下:

type FileRequest struct {
   FileName   string `json:"file_name" form:"file_name" binding:"required"`
   UploadName string `json:"upload_name" form:"upload_name" binding:"required"`
}

func SaveFileHandler(c *gin.Context) {

   req := &FileRequest{}

   if err := c.Bind(req); err != nil {
      log.Printf("err:%v", err)
      c.JSON(http.StatusOK, gin.H{
         "errno":  "1",
         "errmsg": "parameters not match",
      })
      return
   }

   // get the file of the request
   file, _, _ := c.Request.FormFile("file")
   if file == nil {
      c.JSON(http.StatusOK, gin.H{
         "errno":  "2",
         "errmsg": "file is nil",
      })
      return
   }

   fmt.Printf("SaveFile: req:%+vn", req)
   out, err := os.Create("test2.txt")

   if err != nil {
      c.JSON(http.StatusOK, gin.H{
         "errno":  "2",
         "errmsg": err.Error(),
      })
      return
   }

   // copy the content of the file to the out
   _, err = io.Copy(out, file)
   defer file.Close()
   defer out.Close()

   if err != nil {
      c.JSON(http.StatusOK, gin.H{
         "errno":  "2",
         "errmsg": err.Error(),
      })
      return
   }

   c.JSON(http.StatusOK, gin.H{
      "errno":  "0",
      "errmsg": "save file success",
   })
}

再把接口函数设置到路由中,那么单元测试就可以这样来写啦:

func TestSaveFileHandler(t *testing.T) {
   param := make(map[string]interface{})
   param["file_name"] = "test1.txt"
   param["upload_name"] = "Valiben"

   resp := OrdinaryResponse{}
   err := utils.TestFileHandlerUnMarshalResp(utils.POST, "/upload", (param["file_name"]).(string),
      "file", param, &resp)
   if err != nil {
      t.Errorf("TestSaveFileHandler: %vn", err)
      return
   }

   if resp.Errno != "0" {
      t.Errorf("TestSaveFileHandler: response is not expectedn")
      return
   }
}

file_name是文件路径名,可以是相对路径也可以是绝对路径,该测试函数模拟调用/upload请求,上传当前路径下的test1.txt。

除此之外,小demo还支持自定义请求头(诸如jwt-token等),更多用法可以看小demo中的test/handlers_test哦

转载于:https://my.oschina.net/u/3400816/blog/1585130

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_34236497/article/details/92386605
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-06-06 10:46:49
  • 阅读 ( 2518 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢