单元测试 #
一、测试概述 #
1.1 Go测试框架 #
Go内置testing包,提供轻量级的测试框架。
1.2 测试文件命名 #
text
main.go → main_test.go
user.go → user_test.go
handler.go → handler_test.go
二、基本测试 #
2.1 测试函数 #
go
package main
import (
"testing"
)
func TestAdd(t *testing.T) {
result := Add(2, 3)
expected := 5
if result != expected {
t.Errorf("Add(2, 3) = %d; want %d", result, expected)
}
}
2.2 运行测试 #
bash
# 运行所有测试
go test ./...
# 运行特定包
go test ./handlers
# 运行特定测试
go test -run TestAdd
# 显示详细输出
go test -v
# 查看覆盖率
go test -cover
三、Fiber应用测试 #
3.1 测试HTTP处理 #
go
package main
import (
"io"
"net/http/httptest"
"testing"
"github.com/gofiber/fiber/v2"
"github.com/stretchr/testify/assert"
)
func TestHelloHandler(t *testing.T) {
app := fiber.New()
app.Get("/hello", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
req := httptest.NewRequest("GET", "/hello", nil)
resp, err := app.Test(req, -1)
assert.NoError(t, err)
assert.Equal(t, 200, resp.StatusCode)
body, _ := io.ReadAll(resp.Body)
assert.Equal(t, "Hello, World!", string(body))
}
3.2 测试JSON响应 #
go
func TestJSONHandler(t *testing.T) {
app := fiber.New()
app.Get("/user", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"name": "John",
"age": 30,
})
})
req := httptest.NewRequest("GET", "/user", nil)
req.Header.Set("Accept", "application/json")
resp, err := app.Test(req)
assert.NoError(t, err)
assert.Equal(t, 200, resp.StatusCode)
body, _ := io.ReadAll(resp.Body)
assert.Contains(t, string(body), "John")
}
3.3 测试POST请求 #
go
func TestCreateUser(t *testing.T) {
app := fiber.New()
app.Post("/users", func(c *fiber.Ctx) error {
var user struct {
Name string `json:"name"`
Email string `json:"email"`
}
if err := c.BodyParser(&user); err != nil {
return c.Status(400).SendString("Invalid JSON")
}
return c.Status(201).JSON(user)
})
body := `{"name":"John","email":"john@example.com"}`
req := httptest.NewRequest("POST", "/users", strings.NewReader(body))
req.Header.Set("Content-Type", "application/json")
resp, err := app.Test(req)
assert.NoError(t, err)
assert.Equal(t, 201, resp.StatusCode)
}
四、测试中间件 #
4.1 测试认证中间件 #
go
func TestAuthMiddleware(t *testing.T) {
app := fiber.New()
app.Use(func(c *fiber.Ctx) error {
token := c.Get("Authorization")
if token == "" {
return c.Status(401).JSON(fiber.Map{"error": "Unauthorized"})
}
return c.Next()
})
app.Get("/protected", func(c *fiber.Ctx) error {
return c.SendString("Protected")
})
// 测试无Token
t.Run("NoToken", func(t *testing.T) {
req := httptest.NewRequest("GET", "/protected", nil)
resp, _ := app.Test(req)
assert.Equal(t, 401, resp.StatusCode)
})
// 测试有Token
t.Run("WithToken", func(t *testing.T) {
req := httptest.NewRequest("GET", "/protected", nil)
req.Header.Set("Authorization", "Bearer token")
resp, _ := app.Test(req)
assert.Equal(t, 200, resp.StatusCode)
})
}
五、表驱动测试 #
5.1 表驱动测试模式 #
go
func TestValidateEmail(t *testing.T) {
tests := []struct {
name string
email string
expected bool
}{
{"Valid email", "test@example.com", true},
{"Invalid email", "invalid", false},
{"Empty email", "", false},
{"No domain", "test@", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ValidateEmail(tt.email)
assert.Equal(t, tt.expected, result)
})
}
}
六、测试覆盖率 #
6.1 生成覆盖率报告 #
bash
# 查看覆盖率
go test -cover
# 生成覆盖率文件
go test -coverprofile=coverage.out
# 查看覆盖率详情
go tool cover -func=coverage.out
# 生成HTML报告
go tool cover -html=coverage.out -o coverage.html
七、总结 #
7.1 测试要点 #
| 要点 | 说明 |
|---|---|
| 测试文件 | *_test.go |
| 测试函数 | TestXxx |
| 断言 | testify/assert |
| 覆盖率 | go test -cover |
7.2 下一步 #
现在你已经掌握了单元测试,接下来让我们学习 API测试,了解接口测试方法!
最后更新:2026-03-28