使用Golang的Gin框架进行单元测试的最佳实践

使用Golang的Gin框架进行单元测试的最佳实践 我编写了以下代码来测试一个 Gin 函数:

func TestServe(t *testing.T) {
config.SetLoggerConfig("logger.apipath")
router := Serve()

        w := httptest.NewRecorder()
        req, _ := http.NewRequest("GET", "/nodes", nil)
        router.ServeHTTP(w, req)

        assert.Equal(t, 200, w.Code)
}

Serve() 函数返回一个 Gin Engine,当我运行这个测试时,它会卡在以下信息处: [GIN-debug] Listening and serving HTTP on :8080

我该如何解决这个问题?


更多关于使用Golang的Gin框架进行单元测试的最佳实践的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于使用Golang的Gin框架进行单元测试的最佳实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在 Gin 框架中进行单元测试时,不应该启动实际的 HTTP 服务器。你的测试卡住是因为 Serve() 函数内部可能调用了 Run() 方法。以下是正确的单元测试实践:

func TestServe(t *testing.T) {
    // 移除生产环境的配置
    // config.SetLoggerConfig("logger.apipath") 
    
    // 创建测试用的 Gin Engine
    router := gin.New()
    
    // 设置测试路由
    router.GET("/nodes", func(c *gin.Context) {
        c.JSON(200, gin.H{"status": "ok"})
    })
    
    w := httptest.NewRecorder()
    req, _ := http.NewRequest("GET", "/nodes", nil)
    router.ServeHTTP(w, req)
    
    assert.Equal(t, 200, w.Code)
    assert.Contains(t, w.Body.String(), "ok")
}

如果你的 Serve() 函数包含业务逻辑,应该重构它:

// 重构 Serve 函数,使其返回 *gin.Engine 而不启动服务器
func CreateRouter() *gin.Engine {
    router := gin.New()
    router.GET("/nodes", nodesHandler)
    // 其他路由配置...
    return router
}

// 单元测试
func TestNodesEndpoint(t *testing.T) {
    router := CreateRouter()
    
    w := httptest.NewRecorder()
    req, _ := http.NewRequest("GET", "/nodes", nil)
    router.ServeHTTP(w, req)
    
    assert.Equal(t, 200, w.Code)
}

对于需要测试中间件的情况:

func TestAuthMiddleware(t *testing.T) {
    router := gin.New()
    
    // 添加要测试的中间件
    router.Use(AuthMiddleware())
    router.GET("/protected", func(c *gin.Context) {
        c.JSON(200, gin.H{"message": "protected"})
    })
    
    // 测试未授权访问
    w1 := httptest.NewRecorder()
    req1, _ := http.NewRequest("GET", "/protected", nil)
    router.ServeHTTP(w1, req1)
    assert.Equal(t, 401, w1.Code)
    
    // 测试授权访问
    w2 := httptest.NewRecorder()
    req2, _ := http.NewRequest("GET", "/protected", nil)
    req2.Header.Set("Authorization", "Bearer valid-token")
    router.ServeHTTP(w2, req2)
    assert.Equal(t, 200, w2.Code)
}

使用 httptest.NewRecorder()router.ServeHTTP() 可以完全避免启动实际服务器,这是 Gin 框架单元测试的标准做法。

回到顶部