在Rails项目中测试GraphQL,How I Test GraphQL in Rails With RSpec
rellly enjoy using graphql-ruby , when i'm working on new rails apps.
Here is a look into how I go about testing my schema, mutations, and queries.
Dumping the Schema
When you're building your API, your tooling and testing will thank you if dump your GraphQL schema when you make changes in app/graphql.
I use graphql-code-generator >> to generate types and helpers for my fronted code and it requires access to the schema.
The library provides a way to do this yourself by looping in some rake tasks in your Rakefile
Here is a look into how I go about testing my schema, mutations, and queries.
Dumping the Schema
When you're building your API, your tooling and testing will thank you if dump your GraphQL schema when you make changes in app/graphql.
I use graphql-code-generator >> to generate types and helpers for my fronted code and it requires access to the schema.
The library provides a way to do this yourself by looping in some rake tasks in your Rakefile
require 'graphql/rake_task' require_relative 'config/application' Rails.application.load_tasks GraphQL::RakeTask.new( schema_name: 'AppSchema', # this needs to be your generated schema class name )
Now your can use rails grahpql:schema:dump to generate a graphql and json representation of your schema, schema.graphql and schema.json in the root of your rails project by default.
Testing your Schema
测试schema的好处是确保你的tooling is on the same page with the rest of your team. 可以caught by CI.
I like to throw this in spec/graphql/app_schema_spec.rb
require 'rails_helper' RSpec.describe AppSchema do it 'matches the dumped schema (rails graphql:schema:dump)' do aggregate_failures do expect(described_class.to_definition).to eq(File.read(Rails.root.join('schema.graphql')).rstrip) expect(described_class.to_json).to eq(File.read(Rails.root.join('schema.json')).rstrip) end end end
This will ensure that the current dumped schemas match the on-demand generated schema.
这确保当前的dumped schemas 和需要的生产的一致。
RSpec setup
When setting up RSpec I create rspec/support/graphql.rb to plug in helpers and matchers 去帮助和匹配添加内容。plug 插入
module GraphQLHelpers def controller @controller ||= GraphqlController.new.tap do |obj| obj.set_request! ActionDispatch::Request.new({}) end end def execute_graphql(query, **kwargs) AppSchema.execute( query, { context: { controller: controller } }.merge(kwargs), ) end end RSpec.configure do |c| c.include GraphQLHelpers, type: :graphql end
Because I pass { controller: self } as context in GraphqlController, I'm doing similar by replicating an instance of the controller and passing that as context in execute_graphql. This'll be helpful for mocking data.( 模拟数据)
Test Queries and Mutations
Lets say we have defined a login mutation in MutationType
module Mutations class Login < Base null false field :success, Boolean, null: false argument :email, String, required: true argument :password, String, required: true def resolve(email:, password:) user = User.find_by(email: email) user = user&.authenticate(password) context[:controller].session[:user_id] = user.id if user.present? { success: user.present? } end end end
Our mutation takes an email and password, tries to find the user by email, and tries to authenticate them with their password. If it succeeds in finding and authenticating the user, we return success: true
Now we'll test to make sure that it is possible to login with valid credentials, and fail with invalid credentials.
现在我们将测试去确保 它是可能的去登录valid credentials, and fail with invalid credentials.
require 'rails_helper' RSpec.describe Mutations::Login, type: :graphql do let(:mutation) do <<~GQL mutation($input: LoginInput!) { login(input: $input) { success } } GQL end it 'is successful' do user = create(:user) result = execute_graphql( mutation, variables: { input: { email: user.email, password: 'password' } }, ) aggregate_failures do expect(controller.current_user).to eq user expect(result['data']['login']['success']).to eq true end end it 'fails' do result = execute_graphql( mutation, variables: { input: { email: 'whatever', password: 'whatever' } }, ) expect(result['data']['login']['success']).to eq false end end
I hope you're now able to get started in adding coverage for your GraphQL API!
我希望你现在能够开始增加coverage for your GraphQL API.
https://jamesnewton.com/blog/how-i-test-graphql-in-rails-with-rspec
Rails如何使用Graphql分页
https://www.howtographql.com/graphql-ruby/7-filtering/
https://graphql-ruby.org/fields/resolvers.html
阅读量: 689
发布于:
修改于:
发布于:
修改于: