RailsのController Spec


Ruby on Railsのコントローラに対するRSpecの書き方の紹介です。
このドキュメントはRails 5.1、Ruby 2.4.1を前提とします。

🤔 コントローラの責務

コントローラには次の責務があります。ユニットテストでは責務に対するテストを行います。

  • リクエストに対して、適切なレスポンス(ステータスコードなど)を返す
  • ビューの表示に必要なモデルオブジェクトが読み込まれている
  • レスポンスを表示するのに適切なビューを選択する

🏀 環境準備

assignsを使いたいので、Gemfileに以下を入れてbundle installを実行。

gem 'rails-controller-testing'

rails_helperに次の設定を追加。

RSpec.configure do |config|
[:controller, :view, :request].each do |type|
config.include ::Rails::Controller::Testing::TestProcess, type: type
config.include ::Rails::Controller::Testing::TemplateAssertions, type: type
config.include ::Rails::Controller::Testing::Integration, type: type
end
end

🗻 indexアクションのRSpec

rails generate scaffoldしたControllerのindexに対するRSpecです。

describe 'GET #index' do
let(:articles) { create_list(:article, 2) }
before { get :index, params: {}, session: {} }
it 'has a 200 status code' do
expect(response).to have_http_status(:ok)
end
it 'assigns @articles' do
expect(assigns(:articles)).to match_array articles
end
it 'renders the :index template' do
expect(response).to render_template :index
end
end

🚕 showアクションのRSpec

describe 'GET #show' do
let(:article) { create(:article) }
before { get :show, params: { id: article.id }, session: {} }
it 'has a 200 status code' do
expect(response).to have_http_status(:ok)
end
it 'assigns @article' do
expect(assigns(:article)).to eq article
end
it 'renders the :show template' do
expect(response).to render_template :show
end
end

😀 newアクションのRSpec

describe 'GET #new' do
before { get :new, params: {}, session: {} }
it 'has a 200 status code' do
expect(response).to have_http_status(:ok)
end
it 'assigns new @article' do
expect(assigns(:article)).to be_a_new Article
end
it 'renders the :new template' do
expect(response).to render_template :new
end
end

🍄 editアクションのRSpec

describe 'GET #edit' do
let(:article) { create(:article) }
before { get :edit, params: { id: article.id }, session: {} }
it 'has a 200 status code' do
expect(response).to have_http_status(:ok)
end
it 'assigns @article' do
expect(assigns(:article)).to eq article
end
it 'renders the :edit template' do
expect(response).to render_template :edit
end
end

🗽 createアクションのRSpec

describe 'POST #create' do
let(:article_attributes) { attributes_for(:article) }
it 'saves new article' do
expect do
post :create, params: { article: article_attributes }, session: {}
end.to change(Article, :count).by(1)
end
it 'redirects the :create template' do
post :create, params: { article: article_attributes }, session: {}
article = Article.last
expect(response).to redirect_to(article_path(article))
end
end

🐝 updateアクションのRSpec

describe 'PATCH #update' do
let!(:article) { create(:article) }
let(:update_attributes) do
{
title: 'update title',
body: 'update body'
}
end
it 'saves updated article' do
expect do
patch :update, params: { id: article.id, article: update_attributes }, session: {}
end.to change(Article, :count).by(0)
end
it 'updates updated article' do
patch :update, params: { id: article.id, article: update_attributes }, session: {}
article.reload
expect(article.title).to eq update_attributes[:title]
expect(article.body).to eq update_attributes[:body]
end
it 'redirects the :create template' do
patch :update, params: { id: article.id, article: update_attributes }, session: {}
article = Article.last
expect(response).to redirect_to(article_path(article))
end
end

🐡 deleteアクションのRSpec

describe 'DELETE #destroy' do
let!(:article) { create(:article) }
it 'deletes the article' do
expect do
delete :destroy, params: { id: article.id }, session: {}
end.to change(Article, :count).by(-1)
end
it 'redirects the :create template' do
delete :destroy, params: { id: article.id }, session: {}
expect(response).to redirect_to(articles_path)
end
end

🍮 補足:Deviseのログイン認証への対応

ログイン認証を行っている場合はsessionの情報を補完する必要があります。
Deviseでログイン認証を行っている場合は次の記事を参考にしてください。

deviseを使ったコントローラのテスト

🎃 参考リンク

🖥 VULTRおすすめ

VULTR」はVPSサーバのサービスです。日本にリージョンがあり、最安は512MBで2.5ドル/月($0.004/時間)で借りることができます。4GBメモリでも月20ドルです。 最近はVULTRのヘビーユーザーになので、「ここ」から会員登録してもらえるとサービス開発が捗ります!

📚 おすすめの書籍