[RUBY] Various GraphQL tests

Introduction

Recently, I have implemented API with Graphql-ruby. Of course, I need to write a graphql test, but there seem to be various methods, so I will summarize it as a memorandum.

How to actually hit the api

First, I will explain how to actually hit the api. The following is an example.

spec.rb


RSpec.describe User, type: :request do
  describe 'user' do
    it 'The specified usr can be obtained' do
      user = create(:user)

      post '/graphql', params: { query: query(id: user.id) }
      json = JSON.parse(response.body)
      data = json['data']['user']

      expect(data).to include(
        'id' => user.id
      )
      end
    end
  end

  def query(id:)
    <<~GRAPHQL
      query {
        user(id: "#{id}"){
          id
          name
        }
      }
   GRAPHQL
  end
end

It's a straightforward implementation of actually defining a query and posting it to your local api. However, this has some troublesome points as follows.

--rails need to be running --It is troublesome to check each time in parse or json format to expect --context cannot be specified (current_user cannot be specified) --Troublesome to write query

How to hit execute

Next, it is a method to hit execute directly. This is also from the example

spec.rb


RSpec.describe User, type: :request do
  describe 'user' do
    it 'The specified usr can be obtained' do
      user = create(:user)
      
      #Change AppSchema to the defined schema name
      ret = AppSchema.execute(query(id: user.id) context:{current_user: user})
      data = ret['data']['user']

      expect(data).to include(
        'id' => user.id
      )
      end
    end
  end

  def query(id:)
    <<~GRAPHQL
      query {
        user(id: "#{id}"){
          id
          name
        }
      }
   GRAPHQL
  end
end

I received a parse and a response in json, and the description disappeared, which made it a little cleaner. Also, it is easy to test because you can pass context as an argument. On the other hand, writing a query or extracting the id from the json format is tedious. The json format is quite inconvenient, especially when the query is complicated and the nesting is deep.

How to hit only resolver

Let's take a look at an example.

spec.rb


RSpec.describe User, type: :request do
  describe 'resolver' do
    it 'What user can get' do
      user = create(:user)

     # class_name is the resolve class name where the logic is written
      mutation = [class_name].new(field: nil, object: nil, context:{current_user: user})
      ret = mutation.resolve(id: user.id)
      expect(ret).to eq user
    end
  end
end

It was pretty neat. As you can see, I'm reading the resolve method directly by newing the class where resolve is written. With this method, the return value will be a user object, so the test is very easy to write.

How to use

In my case, I use the method of calling execute directly when testing the interface with the front such as ObjectType, and the method of calling resolver directly when testing other logic. I rarely use the method of hitting the first api.

So far, I have summarized the test methods I know. I would be grateful if anyone could comment that there are other good ways.

Recommended Posts

Various GraphQL tests
Various method tests with MockRestServiceServer
FizzBuzz various