# #unit-testing #go #testing #integration-testing
Вопрос:
У нас есть серверная служба GoLang(включена поддержка OAuth), которая принимает http-запросы со Authorization
значением заголовка "Bearer" OAuthTokenString
.
Как написать модульный или интеграционный тестовый случай для серверной службы, чтобы убедиться, что серверная служба включена OAuth(проверяет токен)? я не уверен, что мы не можем создать макет службы( httptest.NewServer
) с включенным OAuth….
Ответ №1:
Это очень интересный вопрос. Я вижу, что ваша команда заботится о минимизации возможных ошибок путем тестирования кода. Это аспект, о котором многие разработчики часто забывают.
Не видя вашего кода, немного сложно предложить 100% правильный ответ для вашего случая.
Я буду считать, что мой пример послужит руководством для написания вашего собственного теста или, в лучшем случае, для оптимизации примера, который я предлагаю
Я использовал gin gonic
в качестве веб-платформы HTTP для своего проекта и написал метод аутентификации, который называется промежуточным программным обеспечением для каждой защищенной конечной точки. Затем для тестирования я создал http-сервер только с помощью gin.Default ()
метода
// 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 = amp;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 = amp;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)
})
}
Комментарии:
1. Я пытаюсь с
httptest.NewServer