You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于公开API测试Go的alexedwards/scs会话功能?

测试alexedwards/scs会话功能的最简方法

问题背景

想要为alexedwards/scs v2编写简单测试,验证会话存取值的一致性,但遇到了以下问题:

第一次编写的测试代码运行时触发panic:scs: no session data in context:

func TestScs_SetGetIsSame1(t *testing.T) {
    sessionManager := scs.New()
    req := httptest.NewRequest("GET", "/", nil)
    key := "boolean"
    expected := false
    sessionManager.Put(req.Context(), key, expected)
    actual := sessionManager.GetBool(req.Context(), key)
    assert.Equal(t, expected, actual)
}

尝试用httptest.Server编写测试时,误用了sessionManager.LoadAndSave(ts)(httptest.Server并非http.Handler类型),代码如下:

func TestScs_SetGetIsSame2(t *testing.T) {
    sessionManager := scs.New()

    ts := httptest.NewServer((http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Hello, client")
        expected := true
        sessionManager.Put(r.Context(), "key", expected)
        actual := sessionManager.GetBool(r.Context(), "key")
        assert.Equal(t, expected, actual)
    })))
    defer ts.Close()

    res, err := http.Get(ts.URL)
    if err != nil {
        log.Fatal(err)
    }

    greeting, err := io.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%s", greeting)

    sessionManager.LoadAndSave(ts)
}

另外注意到scs仓库的测试使用了私有函数addSessionDataToContext,但不想依赖私有实现,因此询问Go中测试会话功能的最佳最简方法。

最简测试方案

方案1:手动初始化会话上下文

scs要求会话数据必须先加载到请求上下文才能读写,直接调用Put会panic是因为上下文没有会话数据。可以使用公开的Load方法手动加载会话到上下文,无需依赖私有函数:

func TestScs_SetGet(t *testing.T) {
    sm := scs.New()
    req := httptest.NewRequest("GET", "/", nil)
    
    // 手动加载会话到请求上下文,空字符串表示新建会话
    ctx, err := sm.Load(req.Context(), "")
    if err != nil {
        t.Fatal(err)
    }
    
    key := "boolean"
    expected := false
    sm.Put(ctx, key, expected)
    actual := sm.GetBool(ctx, key)
    
    assert.Equal(t, expected, actual)
}

方案2:模拟真实HTTP请求流程(贴近实际场景)

如果要测试完整的中间件流程,可使用sessionManager.LoadAndSave作为中间件包裹业务handler,再用httptest.NewRequest和httptest.ResponseRecorder模拟请求,无需启动真实HTTP服务器:

func TestScs_RealFlow(t *testing.T) {
    sm := scs.New()
    // 定义测试handler,在会话中存值并验证一致性
    testHandler := sm.LoadAndSave(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        expected := true
        sm.Put(r.Context(), "key", expected)
        actual := sm.GetBool(r.Context(), "key")
        assert.Equal(t, expected, actual)
        w.WriteHeader(http.StatusOK)
    }))
    
    req := httptest.NewRequest("GET", "/", nil)
    w := httptest.NewRecorder()
    
    // 让handler处理模拟请求
    testHandler.ServeHTTP(w, req)
    
    // 可选:验证响应状态是否符合预期
    assert.Equal(t, http.StatusOK, w.Code)
}

关键说明

  • 方案1适合单元测试,直接测试会话存取值逻辑,跳过HTTP中间件流程,执行速度更快。
  • 方案2更贴近真实运行场景,测试中间件是否正确将会话上下文注入请求,适合集成测试。
  • 不要直接向LoadAndSave传入httptest.Server,它需要接收http.Handler类型,正确用法是用它包裹业务handler。

内容的提问来源于stack exchange,提问作者user2453676

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 02:17:38