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 &mutationResolver{r} } // Query returns generated.QueryResolver implementation. func (r *Resolver) Query() generated.QueryResolver { return &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: &resolvers}))) ue := model.UserEntity{ID: "123", User: model.User{Loginname: &loginname, AvatarURL: &avatarURL}} testUserService.On("ValidateAccessToken", mock.AnythingOfType("string")).Return(&ue) var resp struct { ValidateAccessToken struct{ ID, Loginname, AvatarUrl string } } q := ` mutation { validateAccessToken(accesstoken: "abc") { id, loginname, avatarUrl } } ` c.MustPost(q, &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: &resolvers}))) u := model.UserDetail{User: model.User{Loginname: &loginname, AvatarURL: &avatarURL}, Score: &score, CreateAt: &createAt} testUserService.On("GetUserByLoginname", mock.AnythingOfType("string")).Return(&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, &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 サイトの他の関連記事を参照してください。