在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


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
发布于:
修改于: