【各章まとめ】Everyday Rails - RSpecによるRailsテスト入門 - 第7章 リクエストスペック
Everyday Rails 「RSpecによるRailsテスト入門 - 第7章 リクエストスペック」の復習用まとめ。
letなどは第7章でまだ出てきていないため、DRYではない箇所多数。
GETリクエストのテスト
リクエストスペックの作成
bin/rails g rspec:request projects_api
ファイル名称を変更する
自動生成される spec/requests/projects_apis_spec.rb だとおかしいので、projects_api_spec.rb に変更
テスト実装
RSpec.describe "Projects API", type: :request do it "loads a project" do user = FactoryBot.create(:user) FactoryBot.create(:project, name: "My Project", owner: user) FactoryBot.create(:project, name: "Other user Project") # index アクションのテスト get api_projects_path, params: { user_email: user.email, user_token: user.authentication_token } expect(response).to have_http_status(:success) json = JSON.parse(response.body) expect(json.length).to eq 1 # show アクションのテスト project_id = json[0]["id"] get api_project_path(project_id), params: { user_email: user.email, user_token: user.authentication_token } expect(response).to have_http_status(:success) json = JSON.parse(response.body) expect(json["name"]).to eq "My Project" end end
POSTリクエストのテスト
RSpec.describe "Projects API", type: :request do # index、showのテストは略 it "create a project" do user = FactoryBot.create(:user) project_params = FactoryBot.attributes_for(:project, owner: user) expect do post api_projects_path, params: { user_email: user.email, user_token: user.authentication_token, project: project_params } end.to change(user.projects, :count).by(1) expect(response).to have_http_status(:success) end end
コントローラスペックをリクエストスペックで置き換える
indexのテスト
RSpec.describe "Home Page", type: :request do it "responds successfully" do get root_path # ここはいい感じに読み替える expect(response).to be_success expect(response).to have_http_status "200" end end
createのテスト
- 基本的にコントローラスペックとほぼ同一。
- POSTリクエストの送信方法が post :create から post projects_path と名前付きに変わる。
- Deviceで認証制御している場合は、request spec内で認証用メソッドを呼ぶ設定が必要。
require 'rails_helper' RSpec.describe "Projects", type: :request do describe "#create" do context "ログインしている場合" do let(:user) { FactoryBot.create(:user) } context "有効な属性値の場合" do let(:project_params) { FactoryBot.attributes_for(:project) } it "プロジェクトを追加できる" do sign_in user expect { post projects_path, params: { project: project_params } }.to change(user.projects, :count).by(1) end end context "無効な属性値の場合" do let(:invalid_project_params) { FactoryBot.attributes_for(:project, :invalid) } it "プロジェクトを追加できない" do sign_in user expect { post projects_path, params: { project: invalid_project_params } }.not_to change(user.projects, :count) end end end context "ログインしているが、プロジェクトのオーナーではない場合" do # ... end context "ログインしていない場合" do # ... end end end
request spec内で認証用メソッドを呼ぶ設定をしないとダメ。
公式、もしくは書籍参照。everyday Railsでは簡単な方ではなく、詳細な方の設定をしている。
How To: sign in and out a user in Request type specs (specs tagged with type: :request) · plataformatec/devise Wiki · GitHub
念のためここにも記述。
spec/support/request_spec_helper.rbを作成
module RequestSpecHelper include Warden::Test::Helpers def self.included(base) base.before(:each) { Warden.test_mode! } base.after(:each) { Warden.test_reset! } end def sign_in(resource) login_as(resource, scope: warden_scope(resource)) end def sign_out(resource) logout(warden_scope(resource)) end private def warden_scope(resource) resource.class.name.underscore.to_sym end end
rails_helper.rb
RSpec.configure do |config| # ... # Use Devise helpers in tests config.include Devise::Test::ControllerHelpers, type: :controller config.include RequestSpecHelper, type: :request # ←こいつを追加する end