ホームページ >バックエンド開発 >Golang >Testify と gqlgen/client を使用して Go で GraphQL リゾルバーを単体テストする方法

Testify と gqlgen/client を使用して Go で GraphQL リゾルバーを単体テストする方法

Patricia Arquette
Patricia Arquetteオリジナル
2024-10-28 05:00:01680ブラウズ

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

testify を使用した Go での GraphQL の単体テスト

GraphQL スキーマでは、Query 構造体はデータの取得をトリガーする操作と Mutation 構造体を定義します。状態を変更する操作を定義します。テストするときは、実際の CRUD 操作を実行するオブジェクトをモックし、予期した呼び出しが行われたことをアサートする必要があります。

次の例では、testify パッケージと 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
}

graph/resolver/resolver.go

<code class="go">package resolver

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

type Resolver struct {
    UserService    services.UserService
}</code>

services/user.go

<code class="go">package services

type UserService interface {
    GetUserByLoginname(loginname string) *model.UserDetail
    ValidateAccessToken(accesstoken string) *model.UserEntity
}</code>

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>

GraphQL リクエストとレスポンスをシミュレートするには、次のようにします。サービスのモック オブジェクトを作成できます:

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>

最後に、テスト ファイルでこれらのモックをインポートし、次の目的で使用できます。 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>

このテストは、サービス メソッドに対して正しい呼び出しが行われていることを確認します。 、応答が期待どおりにフォーマットされていることを確認します。テスト カバレッジ レポートには、リゾルバー機能の完全なカバレッジが表示される必要があります。

以上がTestify と gqlgen/client を使用して Go で GraphQL リゾルバーを単体テストする方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。