16
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GraphQLのテストいろいろ

Last updated at Posted at 2020-08-27

はじめに

最近、Graphql-rubyでAPIを実装しています。
当然、graphqlのテストを書く必要があるんですが、いろいろ方法がありそうなので忘備録としてまとめておきます。

実際にapiを叩く方法

まず、実際にapiを叩く方法を説明します。
以下が例になります。

spec.rb
RSpec.describe User, type: :request do
  describe 'user' do
    it '指定したusrが取得できること' 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

queryを実際に定義して、ローカルのapiにpostするという実直な実装です。
しかし、これだと以下のようにいくつか面倒な点があります。

  • expectするためにいちいちパースとかjson形式で確認するのは面倒
  • contextを指定できない(current_userが指定できない)
  • query書くの面倒

executeを叩く方法

続いて、executeを直接叩いてやる方法です。
こちらもまずは例から

spec.rb
RSpec.describe User, type: :request do
  describe 'user' do
    it '指定したusrが取得できること' do
      user = create(:user)
      
      # AppSchemaは定義されているスキーマ名に変えてください
      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

jsonにパースやレスポンスを受け取って記述がなくなり少しすっきりしました。
また、引数にcontextを渡せるのでテストがしやすいです。
一方、queryを書いたり、json形式からidを抜き出したりするのは面倒です。
特にクエリが複雑化してネストが深くなるとjson形式はかなり不便です。

resolverだけ叩く方法

では、早速例をみてみましょう。

spec.rb
RSpec.describe User, type: :request do
  describe 'resolver' do
    it 'userが取得できること' do
      user = create(:user)

     # class_nameはロジックが書かれてるresolveのクラス名
      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

だいぶ、すっきりしました。
見ればわかるかと思いますが、resolveが書いてあるクラスをnewして直接resolveメソッドを読んでいます。この方法ですと、戻り値はuserオブジェクトになるのでテストが非常に書きやすいです。

どれつかう?

自分の場合は、ObjectTypeなどのフロントとのインターフェイスをテストするときにはexecuteを直接呼ぶ方法、それ以外のロジックをテストする場合は、resolverを直接呼ぶ方法を使っています。最初のapiを叩く方法はほとんど使いません。

以上、自分が知ってるテスト方法をまとめてみました。他にも良い方法あるよって人はコメントいただけると嬉しいです。

16
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?