※本サイトで紹介している商品・サービス等の外部リンクには、アフィリエイト広告が含まれる場合があります。
controllerのテスト
controllerにリクエストを送って、想定したレスポンス(httpのステータス)が返ってくるかを確認する(request spec)
controllerの役割を果たせているか確認する
今回は、getリクエストとpostリクエストについてそれぞれテストをしてみる
- 確認したいことを決める
今回は「リクエストを送って、200や正しいレスポンスが返ってくるか」確認したい - リクエストを送る(ダミーデータみたいなもの)
- 200ステータスを確認&レスポンスを確認
- 確認したいことを決める
今回は「リクエストを送って、記事が保存されるか」確認したい - リクエストを送る(ダミーデータみたいなもの)
- postしたパラメーターと、保存された内容が一致しているか確認する
今回はarticles controllerのテストを行う
実際に書いてみる(getリクエスト)
index
にレスポンスを送り、正しいレスポンスが返ってくるか確認したい
def index
@articles = Article.all
end
今回はターミナルからファイルを作ってみる↓
rails g rspec:request article
#=> create spec/requests/articles_spec.rb
すると、spec/requests/articles_spec.rbのファイルが出来上がる↓
require 'rails_helper'
RSpec.describe "Articles", type: :request do
describe "GET /articles" do
it "works! (now write some real specs)" do
get articles_path
expect(response).to have_http_status(200)
end
end
end
↑を↓に書き換える
'GET /articles'
に対して、‘200ステータスが返ってくる’かどうか確認したい
require 'rails_helper'
RSpec.describe 'Articles', type: :request do
describe 'GET /articles' do
it '200ステータスが返ってくる' do
get articles_path
expect(response).to have_http_status(200)
end
end
end
it
以降は‘確認したい内容’を入れる
ダブルクォーテーションはシングルクォーテーションに変えておく(ほかと統一させる)
get articles_path
→getというメソットのおかげで、articles_path
にリクエストを送ることができる
expect(response).to have_http_status(200)
→httpステータスが「200」のresponseが返ってくればokという意味になる
これらはrspecの特殊な書き方だったりする
今の状態でリクエストを送っても通ることは通る
ただ、本当に検証したいのは「記事がある状態でリクエストが通るかどうか」
記事のない状態で検証しても意味がない・・・
記事を用意した状態で、レスポンスが返ってくるのか検証する
RSpec.describe 'Articles', type: :request do
let!(:user) { create(:user) }
let!(:articles) { create_list(:article, 3, user: user) }
let!(:user) { create(:user) }
→記事を作るために、まずはuserを作成する
記事を複数作るのでarticles
とし、creat_list
を使う
(:article
を作ること、3記事作ること、先ほど作った:user
と紐づけること)を記載する
bundle exec rspec spec/requests/articles_spec.rb
成功!

この「・」が緑→テストが通った、赤→テストは失敗という意味
実際に書いてみる(postリクエスト)
「記事が保存されているか」を確認したい
def create
@article = current_user.articles.build(article_params)
if @article.save
redirect_to article_path(@article),
notice: '保存できました'
else
flash.now[:error] = '保存に失敗しました'
render :new
end
end
articles_controller.rbのcreate
の部分はこちら↑
記事を作成後、redirect_to
している
redirect_to
のときは「200」じゃなくて、「302」が返ってくる
ただ、「redirect_to
=記事が保存できている」わけではない
(保存されてなくてもredirect_to
されることがある)
なので、「200」「302」が返ってくるかではなく、記事が保存されているかを確認できるようにする
describe 'POST /articles' do
it '記事が保存される' do
article_params = attributes_for(:article)
post articles_path({article: article_params})
expect(response).to have_http_status(302)
end
end
post
するときはパラメーターを指定しないといけない
article_params
としたとき、attributes_for(:article)
を使うと↓の内容でいい感じにパラメーターを作ってくれる

attributes_for
は、factory_botで用意されている便利なメソッドのひとつ
これでリクエストを送ると、問題なくステータス「302」が返ってくるようになる
次は、「記事が保存されているか」を確認する方法を考える
describe 'POST /articles' do
it '記事が保存される' do
article_params = attributes_for(:article)
post articles_path({article: article_params})
expect(response).to have_http_status(302)
expect(Article.last.title).to eq(article_params[:title])
expect(Article.last.content).to eq(article_params[:content])
end
end
パラメーターで送ったarticle_params
の中身=最後に保存された記事の中身
以下が一致していれば、記事は保存できていることがわかる!
Article.last.title
=article_params[:title]
Article.last.content
=article_params[:content]
Article.last.content
では、content
の本文だけじゃなく、インスタンスとして返ってきてしまう

Article.last.content.body.to_plain_text
コンソール画面で上記のとおり入力してみる

文字列だけ取れた!
ひとまず完成したコードはこちら↓
describe 'POST /articles' do
it '記事が保存される' do
article_params = attributes_for(:article)
post articles_path({article: article_params})
expect(response).to have_http_status(302)
expect(Article.last.title).to eq(article_params[:title])
expect(Article.last.content.to_plain_text).to eq(article_params[:content])
end
end
この状態でテストを実行しても失敗する
現状、ログインしていないからcreate
が出来ず、失敗する
deviceにはsign_in
というメソッドが用意されている
あとはuser
と指定してしまえばログイン状態を作ることができる(簡単!)
describe 'POST /articles' do
context 'ログインしている場合' do
before do
sign_in user
end
it '記事が保存される' do
article_params = attributes_for(:article)
post articles_path({article: article_params})
expect(response).to have_http_status(302)
expect(Article.last.title).to eq(article_params[:title])
expect(Article.last.content.to_plain_text).to eq(article_params[:content])
end
end
end
rspecでdeviceの機能を使うためには、rspecに設定をする必要がある(今のままでは使えない)
spec/rails_helper.rbにFactoryBot
の設定を書いたように、Devise
のinclude
についても記載する
config.include FactoryBot::Syntax::Methods
config.include Devise::Test::IntegrationHelpers, type: :request
「request specでDevice
をインストールします」という意味になる
これで、ログインした状態でリクエストを送ることができる
bundle exec rspec spec/requests/articles_spec.rb
成功!!

#DAY14