【问题标题】:How to write a test case to verify OAuth token?如何编写测试用例来验证 OAuth 令牌?
【发布时间】:2021-08-24 06:11:46
【问题描述】:

我们有一个接受 http 请求的 GoLang 后端服务(启用 OAuth),其标头为 Authorization,值为 "Bearer" + OAuthTokenString

如何为后端服务编写单元或集成测试用例来验证后端服务是否启用了 OAuth(验证令牌)?不确定,我们无法创建启用 OAuth 的模拟服务(httptest.NewServer)....

【问题讨论】:

    标签: unit-testing go testing integration-testing


    【解决方案1】:

    这是一个非常有趣的问题。我可以看到您的团队关心通过测试代码来最大程度地减少可能的错误。这是许多开发人员经常忘记的一个方面。

    没有看过您的代码,很难为您的案例提出 100% 正确的答案。

    我假设我的示例将用作编写您自己的测试的指南,或者在最好的情况下优化我建议的示例

    我使用gin gonic 作为我的项目的 HTTP Web 框架,我编写了一个方法 Authenticate,它被称为每个受保护端点的中间件。然后为了测试我只通过gin.Default ()方法创建了一个http服务器

    // Authenticate auth an endpoint
    func Authenticate() gin.HandlerFunc {
      return func(c *gin.Context) {
        var someErr errors.BukyError
        someErr.SetUnauthorized()
    
        // Fetch token from the headers
        requiredToken := c.GetHeader(constants.AuthorizationHeader)
        if len(requiredToken) == 0 {
            c.AbortWithStatusJSON(someErr.HttpErrorCode, someErr.JSON())
            return
        }
    
        splittedToken := strings.SplitN(requiredToken, " ", 2)
        if len(splittedToken) != 2 || strings.ToLower(splittedToken[0]) != "bearer" {
            primErr := fmt.Errorf("wrong bearer token format on Authorization Header")
            someErr.PrimitiveErr = &primErr
            c.AbortWithStatusJSON(someErr.HttpErrorCode, someErr.JSON())
            return
        }
    
        // Get email from encoded token
        jwtToken, claims, err := helpers.DecodeJWT(splittedToken[1], false)
        if err != nil {
            someErr.PrimitiveErr = &err
            c.AbortWithStatusJSON(someErr.HttpErrorCode, someErr.JSON())
            return
        }
    
        if _, err := helpers.VerifyObjectIDs(claims.Subject); !err.IsNilError() {
            c.AbortWithStatusJSON(someErr.HttpErrorCode, someErr.JSON())
            return
        }
    
        // Set the User variable so that we can easily retrieve from other middlewares
        // c.Set("User", result)
        c.Set(constants.ReqBukyJWTKey, jwtToken)
        c.Set(constants.ReqBukyClaimsKey, claims)
    
        // Call the next middlware
        c.Next()
      }
    }
    

    然后我像下面这样测试

    func TestAuthenticate(t *testing.T) {
      userID := primitive.NewObjectID().Hex()
      email := "email@email.com"
      firstName := "My Name"
      lastName := "My Lastname"
      scopes := []string{"im_scope"}
    
      statusOK := "statusOK"
      someProtectedPath := constants.UsersPath + "/" + userID
    
      engine := gin.Default()
      engine.GET(someProtectedPath, Authenticate(), func(c *gin.Context) {
          c.String(http.StatusOK, statusOK)
      })
    
      t.Run("NoTokenHeader", func(t *testing.T) {
        t.Run("UnsetHeader", func(t *testing.T) {
            w := httptest.NewRecorder()
            req, _ := http.NewRequest("GET", someProtectedPath, nil)
            engine.ServeHTTP(w, req)
            assert.Equal(t, http.StatusUnauthorized, w.Code)
        })
    
        t.Run("EmptyHeader", func(t *testing.T) {
            w := httptest.NewRecorder()
            req, _ := http.NewRequest("GET", someProtectedPath, nil)
            req.Header.Set(constants.AuthorizationHeader, "")
            engine.ServeHTTP(w, req)
            assert.Equal(t, http.StatusUnauthorized, w.Code)
        })
      })
    
      t.Run("TokenWithBadFormat", func(t *testing.T) {
        t.Run("1", func(t *testing.T) {
            w := httptest.NewRecorder()
            req, _ := http.NewRequest("GET", someProtectedPath, nil)
            badFormatedToken := "hola.hola"
            req.Header.Set(constants.AuthorizationHeader, fmt.Sprintf("Bearer %s", badFormatedToken))
            engine.ServeHTTP(w, req)
            assert.Equal(t, http.StatusUnauthorized, w.Code)
        })
    
        t.Run("2", func(t *testing.T) {
            w := httptest.NewRecorder()
            req, _ := http.NewRequest("GET", someProtectedPath, nil)
            badFormatedToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
            req.Header.Set(constants.AuthorizationHeader, fmt.Sprintf("Bearer %s", badFormatedToken))
            engine.ServeHTTP(w, req)
            assert.Equal(t, http.StatusUnauthorized, w.Code)
        })
    
        t.Run("3", func(t *testing.T) {
            w := httptest.NewRecorder()
            req, _ := http.NewRequest("GET", someProtectedPath, nil)
            badFormatedToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.hola.hola.hola"
            req.Header.Set(constants.AuthorizationHeader, fmt.Sprintf("Bearere %s", badFormatedToken))
            engine.ServeHTTP(w, req)
            assert.Equal(t, http.StatusUnauthorized, w.Code)
        })
      })
    
      t.Run("ExpiredToken", func(t *testing.T) {
        w := httptest.NewRecorder()
        req, _ := http.NewRequest("GET", someProtectedPath, nil)
        expirationTime := time.Second
        expiredToken, _, err := helpers.GenerateAccessJWT(userID, email, firstName, lastName, scopes, expirationTime)
        time.Sleep(expirationTime * 2)
        req.Header.Set(constants.AuthorizationHeader, fmt.Sprintf("Bearer %s", expiredToken))
        engine.ServeHTTP(w, req)
        assert.Equal(t, http.StatusUnauthorized, w.Code)
        assert.Nil(t, err)
      })
    
      t.Run("ValidToken", func(t *testing.T) {
        w := httptest.NewRecorder()
        req, _ := http.NewRequest("GET", someProtectedPath, nil)
        validToken, _, err := helpers.GenerateAccessJWT(userID, email, firstName, lastName, scopes)
        req.Header.Set(constants.AuthorizationHeader, fmt.Sprintf("Bearer %s", validToken))
        engine.ServeHTTP(w, req)
        assert.Nil(t, err)
        assert.Equal(t, http.StatusOK, w.Code)
    
      })
    }
    

    【讨论】:

    • 正在尝试httptest.NewServer
    猜你喜欢
    • 1970-01-01
    • 2017-06-10
    • 2021-03-06
    • 2021-10-04
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    相关资源
    最近更新 更多