Maison > développement back-end > Golang > le corps du texte

Comment tester unitairement les résolveurs GraphQL dans Go avec Testify et gqlgen/client ?

Patricia Arquette
Libérer: 2024-10-28 05:00:01
original
560 Les gens l'ont consulté

How to Unit Test GraphQL Resolvers in Go with Testify and gqlgen/client?

Test unitaire de GraphQL dans Go à l'aide de testify

Dans le schéma GraphQL, la structure Query définit les opérations qui déclenchent la récupération des données et la structure Mutation définit les opérations qui modifient l'état. Lors des tests, vous devrez vous moquer des objets qui effectuent les opérations CRUD réelles et affirmer que les appels attendus sont effectués.

Pour l'exemple suivant, nous utiliserons les packages testify et gqlgen/client :

graph/schema.graphql

type Query {
  user(loginname: String!): UserDetail
}

type Mutation {
  validateAccessToken(accesstoken: String!): UserEntity
}

type User { 
  loginname: String 
  avatarUrl: String 
}

type UserEntity {
  id: ID!
  loginname: String 
  avatarUrl: String
}

type UserDetail { 
  loginname: String
  avatarUrl: String
  githubUsername: String
  createAt: String
  score: Int
}
Copier après la connexion

graph/resolver/resolver.go

<code class="go">package resolver

import (
    "github.com/mrdulin/gqlgen-cnode/services"
)

type Resolver struct {
    UserService    services.UserService
}</code>
Copier après la connexion

services/user.go

<code class="go">package services

type UserService interface {
    GetUserByLoginname(loginname string) *model.UserDetail
    ValidateAccessToken(accesstoken string) *model.UserEntity
}</code>
Copier après la connexion

graph/resolver/root.resolver.go

<code class="go">package resolver

import (
    "context"

    "github.com/mrdulin/gqlgen-cnode/graph/generated"
    "github.com/mrdulin/gqlgen-cnode/graph/model"
)

func (r *mutationResolver) ValidateAccessToken(ctx context.Context, accesstoken string) (*model.UserEntity, error) {
    return r.UserService.ValidateAccessToken(accesstoken), nil
}

func (r *queryResolver) User(ctx context.Context, loginname string) (*model.UserDetail, error) {
    return r.UserService.GetUserByLoginname(loginname), nil
}

// Mutation returns generated.MutationResolver implementation.
func (r *Resolver) Mutation() generated.MutationResolver { return &amp;mutationResolver{r} }

// Query returns generated.QueryResolver implementation.
func (r *Resolver) Query() generated.QueryResolver { return &amp;queryResolver{r} }

type mutationResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }</code>
Copier après la connexion

Pour simuler les requêtes et réponses GraphQL, nous peut créer des objets fictifs pour les services :

mocks/userService.go

<code class="go">package mocks

import (
    "github.com/mrdulin/gqlgen-cnode/graph/model"
    "github.com/stretchr/testify/mock"
)

type MockedUserService struct {
    mock.Mock
}

func (s *MockedUserService) GetUserByLoginname(loginname string) *model.UserDetail {
    args := s.Called(loginname)
    return args.Get(0).(*model.UserDetail)
}

func (s *MockedUserService) ValidateAccessToken(accesstoken string) *model.UserEntity {
    args := s.Called(accesstoken)
    return args.Get(0).(*model.UserEntity)
}</code>
Copier après la connexion

Enfin, dans notre fichier de test, nous pouvons importer ces simulacres et les utiliser pour testez nos résolveurs GraphQL :

graph/resolver/root.resolver_test.go

<code class="go">package resolver_test

import (
    "testing"

    "github.com/99designs/gqlgen/client"
    "github.com/99designs/gqlgen/graphql/handler"
    "github.com/mrdulin/gqlgen-cnode/graph/generated"
    "github.com/mrdulin/gqlgen-cnode/graph/model"
    "github.com/mrdulin/gqlgen-cnode/graph/resolver"
    "github.com/mrdulin/gqlgen-cnode/mocks"
    "github.com/stretchr/testify/mock"
    "github.com/stretchr/testify/require"
)

var (
    loginname = "mrdulin"
    avatarURL = "avatar.jpg"
    score     = 50
    createAt  = "1900-01-01"
)

func TestMutationResolver_ValidateAccessToken(t *testing.T) {

    t.Run("should validate accesstoken correctly", func(t *testing.T) {
        testUserService := new(mocks.MockedUserService)
        resolvers := resolver.Resolver{UserService: testUserService}
        c := client.New(handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &amp;resolvers})))
        ue := model.UserEntity{ID: "123", User: model.User{Loginname: &amp;loginname, AvatarURL: &amp;avatarURL}}
        testUserService.On("ValidateAccessToken", mock.AnythingOfType("string")).Return(&amp;ue)
        var resp struct {
            ValidateAccessToken struct{ ID, Loginname, AvatarUrl string }
        }
        q := `
      mutation { 
        validateAccessToken(accesstoken: "abc") { 
          id, 
          loginname, 
          avatarUrl 
        } 
      }
    `
        c.MustPost(q, &amp;resp)
        testUserService.AssertExpectations(t)
        require.Equal(t, "123", resp.ValidateAccessToken.ID)
        require.Equal(t, "mrdulin", resp.ValidateAccessToken.Loginname)
        require.Equal(t, "avatar.jpg", resp.ValidateAccessToken.AvatarUrl)
    })

}

func TestQueryResolver_User(t *testing.T) {
    t.Run("should query user correctly", func(t *testing.T) {
        testUserService := new(mocks.MockedUserService)
        resolvers := resolver.Resolver{UserService: testUserService}
        c := client.New(handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &amp;resolvers})))
        u := model.UserDetail{User: model.User{Loginname: &amp;loginname, AvatarURL: &amp;avatarURL}, Score: &amp;score, CreateAt: &amp;createAt}
        testUserService.On("GetUserByLoginname", mock.AnythingOfType("string")).Return(&amp;u)
        var resp struct {
            User struct {
                Loginname, AvatarURL, CreateAt string
                Score                          int
            }
        }
        q := `
      query GetUser($loginname: String!) { 
        user(loginname: $loginname) { 
          loginname
          avatarUrl 
          createAt 
          score 
        } 
      }
    `
        c.MustPost(q, &amp;resp, client.Var("loginname", "mrdulin"))
        testUserService.AssertCalled(t, "GetUserByLoginname", "mrdulin")
        require.Equal(t, "mrdulin", resp.User.Loginname)
        require.Equal(t, "avatar.jpg", resp.User.AvatarURL)
        require.Equal(t, 50, resp.User.Score)
        require.Equal(t, "1900-01-01", resp.User.CreateAt)
    })
}</code>
Copier après la connexion

Ce test garantira que les appels corrects sont effectués aux méthodes de service , et que les réponses sont formatées comme prévu. Le rapport de couverture des tests doit montrer une couverture complète des fonctions du résolveur.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!