单元测试:gtest 与 HTTP 接口测试

官方测试组件 gtestgithub.com/gogf/gf/v2/test/gtest)是对标准库 testing 的轻量扩展:它不引入新框架,只补齐“测试用例分组 + 常用断言”,官方文档说明复杂场景还可以搭配 testifygoconvey 使用。本章介绍 gtest 基础写法,并给出 HTTP 接口层测试的常用做法。

基本概念

  • gtest.C(t, func(t *gtest.T){...}) 创建一个测试分组(Case),一个 Test* 函数可包含多个 C
  • C 内断言失败会输出统一错误信息并终止当前分组,不影响其他分组继续执行。
  • 断言方法:Assert(宽松比较)、AssertEQ(连类型一起比)、AssertNEAssertNilAssertGT/GE/LT/LEAssertIN/NI(v2.9 起支持 map 键判断)等。
  • 测试包既可用 包名_test,也可直接用 包名(后者才能访问包内私有方法)。

gtest 基本断言

package service_test

import (
    "testing"

    "github.com/gogf/gf/v2/test/gtest"
)

// 被测函数:字符串反转
func Reverse(s string) string {
    runes := []rune(s)
    for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
        runes[i], runes[j] = runes[j], runes[i]
    }
    return string(runes)
}

func Test_Reverse(t *testing.T) {
    gtest.C(t, func(t *gtest.T) {
        t.Assert(Reverse("hello"), "olleh")   // 宽松:值相等即可
        t.AssertEQ(Reverse(""), "")           // 严格:类型也相等
        t.Assert(Reverse("中文"), "文中")      // 多字节安全
    })
    gtest.C(t, func(t *gtest.T) {
        // 每个 C 之间相互隔离,失败互不影响
        t.AssertIN("a", []string{"a", "b"})
        t.AssertNil(nil)
    })
}

命令行执行 go test ./... 即可。gtest 还提供 DataPath/DataContent 方便读取测试包 testdata 目录下的数据文件。

HTTP 接口层测试

接口层测试的关键是“让服务真实跑起来”。规范路由的处理器与 net/http 耦合在 ghttp.Request 上,因此常用做法是:测试内启动一个真实 Server(随机端口),再用 HTTP 客户端请求并断言返回。以下代码使用的组件(g.Server 启动/停止、g.Client 发请求)均有官方文档支持,具体组装方式以官方文档 goframe.org 为准:

package main

import (
    "testing"

    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/net/ghttp"
    "github.com/gogf/gf/v2/test/gtest"
)

func Test_HelloAPI(t *testing.T) {
    s := g.Server("test-server")
    s.BindHandler("/hello", func(r *ghttp.Request) {
        r.Response.WriteJson(g.Map{"code": 0, "data": "hi " + r.Get("name").String()})
    })
    s.SetPort(28080)
    s.Start()
    defer s.Shutdown()

    gtest.C(t, func(t *gtest.T) {
        c := g.Client()
        c.SetPrefix("http://127.0.0.1:28080")
        content := c.GetContent(r.Context(), "/hello?name=john")
        t.Assert(content, `{"code":0,"data":"hi john"}`)
    })
}

说明:r.Context() 在测试中可取 context.Background();若要复用标准库的 httptest,可以把它用于被测的、独立的 http.Handlerhttp.HandlerFunc 组件上(ghttp 的服务路由本身由框架管理,不走 httptest.NewServer),两种工具的适用边界需要分清。

注意点

  • 单元测试要“快而稳”:尽量测纯函数与单层逻辑,数据库依赖用真实测试库并在用例间清理数据。
  • 接口测试的端口要避开开发环境占用,或直接使用框架支持的随机端口能力。
  • 断言失败的报错带堆栈定位,别吞错误、别在断言前 println 大对象。
  • 与 CI 结合时注意测试配置与本地配置分离(如独立 test 数据库、关闭外部依赖)。

小结

gtest 负责“好写断言、分组隔离”,HTTP 冒烟测试负责“验证路由与序列化整体正确”。两者结合,业务函数与接口层都能得到覆盖;更复杂场景再引入 testify/goconvey。全部接口以官方文档 goframe.org 为准。

笔记加载中…