リクエストスペック
リクエストスペックとは
リクエストスペックは、Rails アプリケーションで作成されたバックエンド API の動作を検証するための統合テスト。
システムスペックと同様、アプリケーションの動作をテストするためには単体テストであるコントローラスペックよりもこちらが推奨される。
リクエストスペックの作成
作成コマンド
$ rails g rspec:request projects_api
初期状態のspec/requests/projects_apis_spec.rb
require 'rails_helper'
RSpec.describe "ProjectsApis", type: :request do
describe "GET /projects_apis" do
it "works! (now write some real specs)" do
get projects_apis_path
expect(response).to have_http_status(200)
end
end
end
デフォルトだと、RSpec はファイル名を複数形にするので、projects_apis というファイル名になる。
リネームし、リクエストスペックらしい書き方でテストを追加すると以下のようになる。
spec/requests/projects_api_spec.rb
require 'rails_helper'
RSpec.describe "ProjectsApis", type: :request do
# 1件のプロジェクトを読み出すこと
it 'loads a project' do
user = FactoryBot.create(:user)
FactoryBot.create(:project, name: "Sample Project")
FactoryBot.create(:project, name: "Second Sample Project", owner: user)
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
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 "Second Sample Project"
# などなど
end
# プロジェクトを作成できること
it 'creates a project' do
user = FactoryBot.create(:user)
project_attributes = FactoryBot.attributes_for(:project)
expect {
post api_projects_path, params: {
user_email: user.email,
user_token: user.authentication_token,
project: project_attributes
}
}.to change(user.projects, :count).by(1)
expect(response).to have_http_status(:success)
end
end
コントローラスペックとの相違点
コントローラスペックと違い、好きなルーティング名を指定できる(つまりアクション名に依存せずコントローラとは結びつかない)ので、テストしたいルーティング名を指定できているか確認する必要がある。
API 以外のコントローラのテストをリクエストスペックで書く
API 以外のコントローラのテストをリクエストスペックで書くこともできる。
require 'rails_helper'
RSpec.describe "Projects", type: :request do
# 認証済みのユーザーとして
context "as an authenticated user" do
before do
@user = FactoryBot.create(:user)
end
# 有効な属性値の場合
context "with valid attributes" do
# プロジェクトを追加できること
it "adds a project" do
project_params = FactoryBot.attributes_for(:project)
sign_in @user
expect {
post projects_path, params: { project: project_params }
}.to change(@user.projects, :count).by(1)
end
end
# 無効な属性値の場合
context "with invalid attributes" do
# プロジェクトを追加できないこと
it "does not add a project" do
project_params = FactoryBot.attributes_for(:project, :invalid)
sign_in @user
expect {
post projects_path, params: { project: project_params }
}.to_not change(@user.projects, :count)
end
end
end
end
また、コントローラが標準的なメールアドレスとパスワードの認証システムを使っている場合、上記のテストを機能させるにはDeviseのsign_inヘルパーをリクエストスペックに追加する必要がある。
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
spec/rails_helper.rb
RSpec.configure do |config|
config.include RequestSpecHelper, type: :request
end
参考文献
この記事は以下の情報を参考にして執筆しました。