GraphQL Mutationのテストにて、整数な引数が型エラーで怒られた

RspecでGraphQLのmutationを叩いたときに問題が発生したのでメモ。

mutationが謎に落ちた

下記のようなユーザー登録のmutationのspecを実行しようとした。
(graphql-deviseのmutationをテスト)

let!(:query) do
  <<~GRAPHQL
    mutation userRegister(
      $email: String!
      $password: String!
      $passwordConfirmation: String!
      $gender: Int!
    ) {
      userRegister (
        email: $email,
        password: $password,
        passwordConfirmation: $passwordConfirmation,
        gender: $gender,
      ) {
        credentials {
          accessToken
        }
        user {
          email
          gender
        }
      }
    }
  GRAPHQL
end

let!(:path) { '/graphql_auth' }
let!(:variables) { 
  { 
    email: 'test@example.com', 
    password: 'password1234!', 
    passwordConfirmation: 'password1234!',
    gender: 0,
  } 
}
let!(:params) { { query: query, variables: variables } }
let(:post_request) { post path, params: params }

before do
  post_request
end

it 'ユーザーが作成されている' do
  expect(User.count).to eq 1
end

だがテストが失敗する。。

Failure/Error: expect(Coach.count).to eq 1

  expected: 1
      got: 0

  (compared using ==)
# ./spec/requests/mutations/coach/register.rb:95:in `block (3 levels) in <top (required)>'

Finished in 40.95 seconds (files took 7.89 seconds to load)
1 example, 1 failure

エラーの詳細も出てこず、何が原因かよくわからなかった。

gemの中を見にいく

同僚に相談したところ、gemの中でbinding.pryする方法を教えていただいた。
docekrコンテナでvimを使えるようにした後bundle open graphql_devise
graphql-deviseのファイルを開き、
graphql_devise/graphql_controller.rbbinding.pryを差し込む。

再びテストを実行すると止まってくれた。

    9: def auth
    10:   binding.pry
    11:   result = if params[:_json]
    12:     GraphqlDevise::Schema.multiplex(
    13:       params[:_json].map do |param|
    14:         { query: param[:query] }.merge(execute_params(param))
    15:       end
    16:     )
    17:   else
 => 18:     GraphqlDevise::Schema.execute(params[:query], **execute_params(params))
    19:   end
    20:
    21:   render json: result unless performed?
    22: end

ここで
GraphqlDevise::Schema.execute(params[:query], **execute_params(params))
を実行してみると次のようなエラーが出た。

[1] pry(#<GraphqlDevise::GraphqlController>)> GraphqlDevise::Schema.execute(params[:query], **execute_params(params)).to_h
=> {"errors"=>
  [{"message"=>"Variable $gender of type Int! was provided invalid value",
    "locations"=>[{"line"=>9, "column"=>3}],
    "extensions"=>
     {"value"=>"0", "problems"=>[{"path"=>[], "explanation"=>"Could not coerce value \"0\" to Int"}]}}]}

$genderは整数を期待しているが"0"という文字列が渡っているらしい。 困惑・・。

パラメータをjsonにして解決した

調べているとこちらのissueを発見。
コメントを読むとRailsが文字列としか認識できていないとのこと。
またそれを回避するにはjsonにしてあげる必要があるようです。

let!(:params) { { query: query, variables: variables.to_json } } # to_jsonを加えた
let(:post_request) { post path, params: params }

このようにしてmutationが正常に実行され、無事テストも通すことができました。