在 Golang 中对 GraphQL 进行单元测试 [英] unit testing GraphQL in Golang

查看:16
本文介绍了在 Golang 中对 GraphQL 进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这种情况下我使用

  • 回声
  • mongo-driver (MongoDB)
  • gqlgen

    源代码:https://github.com/mrdulin/gqlgen-cnode>

    in this case I am using

    is there any simple example for testing my Mutation and Query ? I do love to get advices for this. I have tried to find but can't found any so far,

    thank you :)

    解决方案

    Here is an test example using testify package and the gqlgen/client package which is used internally for testing.

    GraphQL schema:

    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:

    package resolver
    
    import "github.com/mrdulin/gqlgen-cnode/services"
    
    // This file will not be regenerated automatically.
    //
    // It serves as dependency injection for your app, add any dependencies you require here.
    
    type Resolver struct {
        UserService    services.UserService
    }
    

    services/user.go:

    package services
    
    type UserService interface {
        GetUserByLoginname(loginname string) *model.UserDetail
        ValidateAccessToken(accesstoken string) *model.UserEntity
    }
    

    graph/resolver/root.resolver.go:

    package resolver
    
    // This file will be automatically regenerated based on the schema, any resolver implementations
    // will be copied through when generating and any unknown code will be moved to the end.
    
    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 }
    

    Created mock object for UserService:

    mocks/userService.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)
    }
    

    graph/resolver/root.resolver_test.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)
        })
    }
    

    test result:

    === RUN   TestMutationResolver_ValidateAccessToken
    === RUN   TestMutationResolver_ValidateAccessToken/should_validate_accesstoken_correctly
        TestMutationResolver_ValidateAccessToken/should_validate_accesstoken_correctly: root.resolvers_test.go:44: PASS:    ValidateAccessToken(mock.AnythingOfTypeArgument)
    --- PASS: TestMutationResolver_ValidateAccessToken (0.00s)
        --- PASS: TestMutationResolver_ValidateAccessToken/should_validate_accesstoken_correctly (0.00s)
    === RUN   TestQueryResolver_User
    === RUN   TestQueryResolver_User/should_query_user_correctly
    --- PASS: TestQueryResolver_User (0.00s)
        --- PASS: TestQueryResolver_User/should_query_user_correctly (0.00s)
    PASS
    ok      github.com/mrdulin/gqlgen-cnode/graph/resolver  0.141s
    

    test coverage report:

    source code: https://github.com/mrdulin/gqlgen-cnode

    这篇关于在 Golang 中对 GraphQL 进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆