iTranslated by AI
How to Test GraphQL Resolvers with RSpec
Previously, I was writing (or rather, there was) the following Resolvers and their corresponding tests.
The code has been slightly modified.
module Resolvers
class Users < Resolvers::Base
type ObjectTypes::User.connection_type, null: false
description 'Find users by roles. You can pass XXX_role or [XXX_role, YYY_role].'
argument :role, [EnumTypes::User::Role]
def resolve(role:)
if role&.include?('evaluation_role')
User.evaluation_users
elsif role&.include?('level_aptitude_role')
User.level_aptitude_users
else
User.where(role: role)
end
end
end
end
require 'rails_helper'
RSpec.describe Resolvers::Users do
describe '#resolve' do
context 'when role includes evaluation_role' do
it 'returns evaluation test users filtered by service' do
user1 = create(:user, role: 'evaluation_role')
user2 = create(:user, role: 'evaluation_role')
allow(User).to receive(:evaluation_test_users).and_return([user1, user2])
result = described_class.new(object: nil, field: nil, context: nil).resolve(role: ['evaluation_role'])
expect(result).to contain_exactly(user1, user2)
end
end
end
end
When I upgraded the graphql-ruby version from 2.3.7 to 2.3.10, I began encountering an undefined method types' for nil:NilClass` error.
This change was caused by the modification linked below. I opened an issue to inquire with the author, who informed me that Resolvers are not supported outside of GraphQL queries.
The author suggested the following two alternatives:
- Use the
run_graphql_fieldhelper, which provides a complete GraphQL context. - Alternatively, create a dummy
Query::Contextinstance and pass it instead ofcontext: nil.- Although this is outside the scope of GraphQL-Ruby's public API, they mentioned it should work for the time being.
query_ctx = GraphQL::Query.new(MySchema, "{ __typename }").context
In this instance, we opted for the former approach, but I will provide sample code for both.
require 'rails_helper'
RSpec.describe Resolvers::Users, type: :graphql do
describe '#resolve' do
subject { run_graphql_field("Query.users", nil, arguments: { role: role }).items }
let!(:user1) { create(:user, role: 'evaluation_role') }
let!(:user2) { create(:user, role: 'evaluation_role') }
context 'when role includes evaluation_role' do
let(:role) { 'evaluation_role' }
it {
expect(subject).to eq [user2, user2]
}
end
end
end
require 'rails_helper'
RSpec.describe Resolvers::Users do
describe '#resolve' do
subject { resolver.resolve(role: role) }
let(:query_ctx) { GraphQL::Query.new(TofflerSchema, "{ __typename }").context }
let(:resolver) { described_class.new(object: nil, context: query_ctx, field: nil) }
let!(:user1) { create(:user, role: 'evaluation_role') }
let!(:user2) { create(:user, role: 'evaluation_role') }
context 'when role includes evaluation_role' do
let(:role) { 'evaluation_role' }
it {
expect(subject).to eq [user2, user1]
}
end
end
end
Additionally, the helper is configured as follows:
config.with_options type: :graphql do |graphql_config|
graphql_config.include GraphQL::Testing::Helpers.for(MySchema)
end
The issue containing this discussion can be found here:
ref. https://github.com/rmosolgo/graphql-ruby/issues/5040
In this case, we chose the first method, which uses run_graphql_field. While the approach using a dummy Query::Context instance requires fewer changes to the existing codebase, we decided that run_graphql_field would be better for future maintenance since the other method is not part of the public API.
Discussion