Webエンジニア1年生がRSpecで
「パスにクエリを渡したい!
でもFactoryBotで作成したテストデータの中身をどうやってパスに渡すの?」
と苦労したけど、実がとても簡単だった話
開発環境
- Ruby 2.5.5
- Rails 5.2.3
- RSpec 3.8
実現したいこと
FactoryBot + RSpecでページ遷移の際にパスにクエリを渡し、それが正しいことをexpectしたい
(http://○○.com/reviews/new ?item_id=20)←クエリ
先に結論
assignsメソッドを使う!
例
とある商品のレビューをするサイトを作っているとする
商品検索画面から商品を選択後、その商品のレビュー投稿ページへ商品IDをパスに持たせて遷移する場合
class ItemsController < ApplicationController
def search
@item = #(フォームから送られてきた商品情報)
# 〜中略〜
redirect_to new_review_path(item_id: @item.id)
# 商品idを渡してレビューページへ遷移する
# /reviews/new?item_id=20
end
end
これが正しく遷移することをRSpecでテストします。
FactoryBot.define do
factory :item, class: Item do
id { 1 }
name { 'ボールペン' }
# 〜中略〜
end
end
require 'rails_helper'
RSpec.describe ItemsController, type: :controller do
describe 'POST #search' do
before do
post :search, params: { item: attributes_for(:item) }
# attributes_for(:item) = { id: 1, name: 'ボールペン', ・・・〜中略〜・・・ }
end
it '選択された商品のレビューページへ遷移する' do
expect(response).to redirect_to new_review_path(item_id: assigns(:item).id)
end
end
end
assignsメソッドとは
コントローラのインスタンス変数に代入されたオブジェクトは、コントローラの assigns メソッド経由で参照できます。
参照する場合には、インスタンス変数名から “@” を除いたものをシンボルまたは文字列にしたものをキーとして指定します。
@itemをassigns(:item)に書き換えることで使えるようになるんですね!
redirect_to new_review_path(item_id: @item.id)
↓
redirect_to new_review_path(item_id: assigns(:item).id)
参考記事
・ スはスペックのス 【第 2 回】 RSpec on Rails (コントローラとビュー編)
https://magazine.rubyist.net/articles/0023/0023-Rspec.html#assigns-%E3%81%AB%E3%82%88%E3%82%8B%E5%8F%82%E7%85%A7