RailsのAPIテストの書き方


準備

Rails を api モードで作成

$ rails new rails-api --api
$ cd rails-api
$ bundle install
$ rails s

http://localhost:3000/ へアクセス

User モデル関連のリソースを scaffold で作成

$ rails generate scaffold User name:string

コンソールでユーザーを作成

$ rails c

> User.create! name: "山田太郎"

http://localhost:3000/users/ にアクセスして、ユーザーが作成されているか確認

Rspec をインストール
Gemfile

group :test do
  gem 'rspec-rails'
end
$ bundle install
$ rails generate rspec:install

テストファイルを作成

$ rails g rspec:request users_api

json ヘルパーを作成
rspec/support/request_helpers

module Requests
  module JsonHelpers
    def json
      JSON.parse(response.body)
    end
  end
end

rails_helper
rails_helper.rb




Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f } # コメントを外す



RSpec.configure do |config|



  config.include Requests::JsonHelpers, type: :request # ヘルパーを読み込む
end

Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
は、rspec/support 以下のファイルを読み込むための設定です。

factry bot をインストール
Gemfile

group :test do
  gem 'rspec-rails'
  gem 'factory_bot_rails'
end

rails_helper.rb

RSpec.configure do |config|



  config.include FactoryBot::Syntax::Methods # 追加
  config.include Requests::JsonHelpers, type: :request
end

FactyBot のメソッドを使うための設定を記述
support/factry_bot.rb

RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end

user ファイルを作成

$ rails g factory_bot:model user

factry/user.rb

FactoryBot.define do
  factory :user do
    sequence(:name) { |n| "TEST_NAME#{n}"}
  end
end

テストを書く

GET の例

  describe "GET /users" do
    before do
      create_list(:user, 10)
    end
    it 'ユーザー一覧が表示されること' do
      get "/users"
      expect(response.status).to eq(200)
      expect(json.length).to eq(User.count)
    end
  end

  describe "GET /users/1" do
    before do
      @user = create(:user)
    end
    it 'ユーザーの詳細が表示されること' do
      get "/users/#{@user.id}"
      expect(response.status).to eq(200)
      expect(json['name']).to eq(@user.name)
    end
  end

POST の例

  describe "POST /users" do
    before do
      @user_create_params = {
        user: {
          name: "user_name"
        }
      }
    end
    it 'ユーザーが作成されること' do
      expect do
        post "/users", params: @user_create_params
        expect(response.status).to eq(201)
      end.to change {User.count}.by(1)
    end
  end

PUT の例

  describe "PUT /users/1" do
    before do
      @user = create(:user)
      @user_update_params = {
        user: {
          name: "new_user_name"
        }
      }
    end
    it 'ユーザーが更新されること' do
      put "/users/#{@user.id}", params: @user_update_params
      expect(response.status).to eq(200)
      expect(@user.reload.name).to eq(@user_update_params[:user][:name])
    end
  end

DELETE の例

  describe "DELETE /users/1" do
    before do
      @user = create(:user)
    end

    it 'ユーザーが削除されること' do
      expect do
        delete "/users/#{@user.id}"
        expect(response.status).to eq(204)
      end.to change{ User.count }.by(-1)
    end
  end

全体

require 'rails_helper'

RSpec.describe "UsersApis", type: :request do
  describe "GET /users" do
    before do
      create_list(:user, 10)
    end
    it 'ユーザー一覧が表示されること' do
      get "/users"
      expect(response.status).to eq(200)
      expect(json.length).to eq(User.count)
    end
  end

  describe "GET /users/1" do
    before do
      @user = create(:user)
    end
    it 'ユーザーの詳細が表示されること' do
      get "/users/#{@user.id}"
      expect(response.status).to eq(200)
      expect(json['name']).to eq(@user.name)
    end
  end

  describe "POST /users" do
    before do
      @user_create_params = {
        user: {
          name: "user_name"
        }
      }
    end
    it 'ユーザーが作成されること' do
      expect do
        post "/users", params: @user_create_params
        expect(response.status).to eq(201)
      end.to change {User.count}.by(1)
    end
  end

  describe "PUT /users/1" do
    before do
      @user = create(:user)
      @user_update_params = {
        user: {
          name: "new_user_name"
        }
      }
    end
    it 'ユーザーが更新されること' do
      put "/users/#{@user.id}", params: @user_update_params
      expect(response.status).to eq(200)
      expect(@user.reload.name).to eq(@user_update_params[:user][:name])
    end
  end

  describe "DELETE /users/1" do
    before do
      @user = create(:user)
    end

    it 'ユーザーが削除されること' do
      expect do
        delete "/users/#{@user.id}"
        expect(response.status).to eq(204)
      end.to change{ User.count }.by(-1)
    end
  end
end