golang路由框架API接口测试插件库gofight的使用
Golang路由框架API接口测试插件库gofight的使用
简介
Gofight是一个用于Golang Web框架的API处理程序测试库,支持多种流行的Golang Web框架。
支持的框架
- Http Handler (Golang标准库net/http)
- Gin框架
- Echo框架 (v3.0.0及以上版本)
- Mux框架
安装
下载该包:
go get github.com/appleboy/gofight/v2
在代码中导入:
import "github.com/appleboy/gofight/v2"
使用示例
基本Hello World测试
主程序:
package main
import (
"io"
"net/http"
)
func BasicHelloHandler(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello World")
}
func BasicEngine() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/", BasicHelloHandler)
return mux
}
测试代码:
package main
import (
"net/http"
"testing"
"github.com/appleboy/gofight/v2"
"github.com/stretchr/testify/assert"
)
func TestBasicHelloWorld(t *testing.T) {
r := gofight.New()
r.GET("/").
// 开启调试模式
SetDebug(true).
Run(BasicEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, "Hello World", r.Body.String())
assert.Equal(t, http.StatusOK, r.Code)
})
}
设置Header
可以使用SetHeader
函数添加自定义Header:
func TestBasicHelloWorld(t *testing.T) {
r := gofight.New()
version := "0.0.1"
r.GET("/").
// 开启调试模式
SetDebug(true).
SetHeader(gofight.H{
"X-Version": version,
}).
Run(BasicEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, version, rq.Header.Get("X-Version"))
assert.Equal(t, "Hello World", r.Body.String())
assert.Equal(t, http.StatusOK, r.Code)
})
}
提交表单数据
使用SetForm
生成表单数据:
func TestPostFormData(t *testing.T) {
r := gofight.New()
r.POST("/form").
SetForm(gofight.H{
"a": "1",
"b": "2",
}).
Run(BasicEngine(), func(r HTTPResponse, rq HTTPRequest) {
data := []byte(r.Body.String())
a, _ := jsonparser.GetString(data, "a")
b, _ := jsonparser.GetString(data, "b")
assert.Equal(t, "1", a)
assert.Equal(t, "2", b)
assert.Equal(t, http.StatusOK, r.Code)
})
}
提交JSON数据
使用SetJSON
生成JSON数据:
func TestPostJSONData(t *testing.T) {
r := gofight.New()
r.POST("/json").
SetJSON(gofight.D{
"a": 1,
"b": 2,
}).
Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {
data := []byte(r.Body.String())
a, _ := jsonparser.GetInt(data, "a")
b, _ := jsonparser.GetInt(data, "b")
assert.Equal(t, 1, int(a))
assert.Equal(t, 2, int(b))
assert.Equal(t, http.StatusOK, r.Code)
assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type"))
})
}
提交原始数据
使用SetBody
生成原始数据:
func TestPostRawData(t *testing.T) {
r := gofight.New()
r.POST("/raw").
SetBody("a=1&b=1").
Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {
data := []byte(r.Body.String())
a, _ := jsonparser.GetString(data, "a")
b, _ := jsonparser.GetString(data, "b")
assert.Equal(t, "1", a)
assert.Equal(t, "2", b)
assert.Equal(t, http.StatusOK, r.Code)
})
}
设置查询字符串
使用SetQuery
生成查询字符串:
func TestQueryString(t *testing.T) {
r := gofight.New()
r.GET("/hello").
SetQuery(gofight.H{
"a": "1",
"b": "2",
}).
Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {
assert.Equal(t, http.StatusOK, r.Code)
})
}
设置Cookie
使用SetCookie
设置Cookie:
func TestQueryString(t *testing.T) {
r := gofight.New()
r.GET("/hello").
SetCookie(gofight.H{
"foo": "bar",
}).
Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {
assert.Equal(t, http.StatusOK, r.Code)
assert.Equal(t, "foo=bar", rq.Header.Get("cookie"))
})
}
设置JSON结构体
type User struct {
// Username 用户名
Username string `json:"username"`
// Password 账户密码
Password string `json:"password"`
}
func TestSetJSONInterface(t *testing.T) {
r := New()
r.POST("/user").
SetJSONInterface(User{
Username: "foo",
Password: "bar",
}).
Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) {
data := []byte(r.Body.String())
username := gjson.GetBytes(data, "username")
password := gjson.GetBytes(data, "password")
assert.Equal(t, "foo", username.String())
assert.Equal(t, "bar", password.String())
assert.Equal(t, http.StatusOK, r.Code)
assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type"))
})
}
上传多个文件
路由处理程序(Gin框架):
func gintFileUploadHandler(c *gin.Context) {
ip := c.ClientIP()
hello, err := c.FormFile("hello")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
helloFile, _ := hello.Open()
helloBytes := make([]byte, 6)
helloFile.Read(helloBytes)
world, err := c.FormFile("world")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
worldFile, _ := world.Open()
worldBytes := make([]byte, 6)
worldFile.Read(worldBytes)
foo := c.PostForm("foo")
bar := c.PostForm("bar")
c.JSON(http.StatusOK, gin.H{
"hello": hello.Filename,
"world": world.Filename,
"foo": foo,
"bar": bar,
"ip": ip,
"helloSize": string(helloBytes),
"worldSize": string(worldBytes),
})
}
测试代码:
func TestUploadFile(t *testing.T) {
r := New()
r.POST("/upload").
SetDebug(true).
SetFileFromPath([]UploadFile{
{
Path: "./testdata/hello.txt",
Name: "hello",
},
{
Path: "./testdata/world.txt",
Name: "world",
},
}, H{
"foo": "bar",
"bar": "foo",
}).
Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) {
data := []byte(r.Body.String())
hello := gjson.GetBytes(data, "hello")
world := gjson.GetBytes(data, "world")
foo := gjson.GetBytes(data, "foo")
bar := gjson.GetBytes(data, "bar")
ip := gjson.GetBytes(data, "ip")
helloSize := gjson.GetBytes(data, "helloSize")
worldSize := gjson.GetBytes(data, "worldSize")
assert.Equal(t, "world\n", helloSize.String())
assert.Equal(t, "hello\n", worldSize.String())
assert.Equal(t, "hello.txt", hello.String())
assert.Equal(t, "world.txt", world.String())
assert.Equal(t, "bar", foo.String())
assert.Equal(t, "foo", bar.String())
assert.Equal(t, "", ip.String())
assert.Equal(t, http.StatusOK, r.Code)
assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type"))
})
}
许可证
Copyright 2019 Bo-Yi Wu @appleboy.
根据MIT许可证授权。
更多关于golang路由框架API接口测试插件库gofight的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang路由框架API接口测试插件库gofight的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
GoFight - Golang路由框架API接口测试插件库使用指南
GoFight是一个专门为Golang路由框架设计的API接口测试插件库,它可以帮助开发者方便地对基于Gin、Echo等流行框架开发的API进行测试。
安装
go get -u github.com/appleboy/gofight
基本使用
测试Gin框架API
package main
import (
"net/http"
"testing"
"github.com/appleboy/gofight"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)
func setupGinRouter() *gin.Engine {
gin.SetMode(gin.TestMode)
r := gin.New()
r.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "welcome",
})
})
r.POST("/login", func(c *gin.Context) {
username := c.PostForm("username")
password := c.PostForm("password")
if username == "admin" && password == "123456" {
c.JSON(http.StatusOK, gin.H{
"status": "logged in",
})
return
}
c.JSON(http.StatusUnauthorized, gin.H{
"status": "unauthorized",
})
})
return r
}
func TestGinHelloWorld(t *testing.T) {
r := setupGinRouter()
g := gofight.New()
g.GET("/").
SetDebug(true).
Run(r, func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusOK, r.Code)
assert.Equal(t, "{\"message\":\"welcome\"}", r.Body.String())
})
}
func TestGinLogin(t *testing.T) {
r := setupGinRouter()
g := gofight.New()
g.POST("/login").
SetForm(gofight.H{
"username": "admin",
"password": "123456",
}).
Run(r, func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusOK, r.Code)
assert.Equal(t, "{\"status\":\"logged in\"}", r.Body.String())
})
g.POST("/login").
SetForm(gofight.H{
"username": "admin",
"password": "wrong",
}).
Run(r, func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusUnauthorized, r.Code)
assert.Equal(t, "{\"status\":\"unauthorized\"}", r.Body.String())
})
}
测试Echo框架API
package main
import (
"net/http"
"testing"
"github.com/appleboy/gofight"
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert"
)
func setupEchoRouter() *echo.Echo {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.JSON(http.StatusOK, map[string]string{
"message": "welcome",
})
})
e.POST("/login", func(c echo.Context) error {
username := c.FormValue("username")
password := c.FormValue("password")
if username == "admin" && password == "123456" {
return c.JSON(http.StatusOK, map[string]string{
"status": "logged in",
})
}
return c.JSON(http.StatusUnauthorized, map[string]string{
"status": "unauthorized",
})
})
return e
}
func TestEchoHelloWorld(t *testing.T) {
e := setupEchoRouter()
g := gofight.New()
g.GET("/").
SetDebug(true).
Run(e, func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusOK, r.Code)
assert.Equal(t, "{\"message\":\"welcome\"}\n", r.Body.String())
})
}
func TestEchoLogin(t *testing.T) {
e := setupEchoRouter()
g := gofight.New()
g.POST("/login").
SetForm(gofight.H{
"username": "admin",
"password": "123456",
}).
Run(e, func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusOK, r.Code)
assert.Equal(t, "{\"status\":\"logged in\"}\n", r.Body.String())
})
}
高级功能
设置请求头
g.GET("/protected").
SetHeader(gofight.H{
"Authorization": "Bearer abc123",
}).
Run(r, func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
// 测试逻辑
})
发送JSON请求体
g.POST("/api/users").
SetJSON(gofight.H{
"name": "John Doe",
"email": "john@example.com",
}).
Run(r, func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
// 测试逻辑
})
测试文件上传
g.POST("/upload").
SetFile(gofight.H{
"file": "testdata/gofight.txt",
}).
Run(r, func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
// 测试逻辑
})
测试查询参数
g.GET("/search").
SetQuery(gofight.H{
"q": "golang",
"limit": "10",
}).
Run(r, func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
// 测试逻辑
})
优势特点
- 简单易用:API设计简洁,学习成本低
- 多框架支持:支持Gin、Echo等多种流行Golang路由框架
- 功能全面:支持GET、POST、PUT、DELETE等多种HTTP方法
- 调试方便:提供SetDebug方法方便调试
- 类型安全:使用gofight.H类型确保参数类型安全
GoFight是Golang API测试的一个轻量级解决方案,特别适合在开发过程中快速验证API接口的正确性。它能够与标准testing包无缝集成,是Golang开发者工具箱中的一个实用工具。