在 go 中测试 Web 应用程序

问题描述 投票:0回答:1

我正在关注 Alex Edwards 的 Let's Go,并一直在尝试对处理程序进行单元测试。我坚持的一件事是我无法正确测试只能通过身份验证访问的端点;至少以干净的方式。

由于我使用 scs 作为我的会话管理器,我无法想出方法来集成到本书提出的相同方法中。本书建议从单元测试中调用以下测试助手。

func newTestApplication(t *testing.T) *application which sets the sessionManager, logs and models,etc.

func newTestServer(t *testing.T, h http.Handler) *testServer sets up the testserver

func (ts *testServer) get(t *testing.T, urlPath string) (int, http.Header, string) handles get methods

假设HandlerA只能被经过身份验证的用户访问;

TestHandlerA{

app := newTestApplication(t)

ts := newTestServer(t, app.routes())

defer ts.Close()
//test cases 

for _, tt := range tests{
    t.Run(tt.name, func(t *testing.T){
           ts.get(t, tt.urlPath)
//assertions
     })
}`

我希望能够提供经过身份验证的用户的 ID,然后进行测试 有什么建议吗?

信息: 当用户登录时,我将经过身份验证的用户 ID 的请求上下文添加到会话管理器。会话管理器加载并保存,并且请求通过中间件进行,该中间件检查用户是否经过身份验证,然后允许用户访问受限端点.

此外,我很想知道人们用于测试受限制的身份验证/授权背后的端点的其他模式。

authentication go testing web-applications
1个回答
0
投票

测试经过身份验证的路由可能很棘手,以下是我会使用的一些策略:

模拟认证 在您的测试设置中,您可以模拟身份验证机制来模拟正在登录的用户。本质上,您将绕过实际的身份验证过程并将模拟用户插入到会话中。

例如,您可以更新 newTestApplication(t *testing.T) 函数以允许将模拟经过身份验证的用户插入到会话中:

   func newTestApplication(t *testing.T, mockUserID string) *application {
    // your code

    // mock the session if mockUserID is set
    if mockUserID != "" {
        app.sessionManager.Put(r.Context(), "authenticatedUserID", mockUserID)
    }
    return app
}

直接设置会话 由于您使用 SCS 进行会话管理,因此您可以在测试期间直接与会话交互,以将用户设置为经过身份验证:

    func setSessionAuthenticated(session *scs.SessionManager, userID string) {
    // You would typically set this in your middleware
    session.Put(context.Background(), "authenticatedUserID", userID)
}

在创建测试应用程序之后并向经过身份验证的路由发出任何请求之前,您可以在测试设置中调用此方法:

    tests := []struct {
    name        string
    urlPath     string
    mockUserID  string
    wantStatus  int
    // ... other fields
}{
    {"Unauthorized", "/restricted", "", http.StatusUnauthorized},
    {"Authorized", "/restricted", "mockUserID", http.StatusOK},
    // ... other test cases
}

for _, tt := range tests {
    t.Run(tt.name, func(t *testing.T) {
        app := newTestApplication(t, tt.mockUserID)
        ts := newTestServer(t, app.routes())
        defer ts.Close()

        status, _, _ := ts.get(t, tt.urlPath)
        
        if status != tt.wantStatus {
            t.Errorf("want %d; got %d", tt.wantStatus, status)
        }

        // ... other assertions
    })
}

尝试结合这些策略,对我很有帮助。

干杯......

© www.soinside.com 2019 - 2024. All rights reserved.