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.
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
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.
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.
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.