subject(:response)
僕はRailsでController書いている時に一つのactionについて、こんな風にspecを書く事が多いです。
subject(:response) do # ←ココ
get :index
end
it { expect(response.status).to eq 200 }
これは普通に考えると、rspec-railsで自動的にresponseを作ってるし、既にあるものを上書きしているようで気持ち悪いところもあるんですが、get(post, putなども同様)の返り値も同じなのでまあ従来と同じようにresponseを使ってテストできます。
なぜわざわざsubject(:response)
と書くのか
まずsubjectを使うと「ここではこれをテストするんだな」と分かりやすくて個人的に好きというのがあります。
その上でsubject(:response)
と書かずにsubject
とした場合はspecはこんな感じになるかと思います
# subject(:response)ってやらない場合
subject do
get :index
end
# これだとsubjectがresponseだって分かりにくい
it { expect(subject.status).to eq 200 }
# これだと既に書いてあるgetと同じもの書くのが面倒(渡す値多いとなおさら)
it do
get :index
expect(response.status).to eq 200
end
# これだとわざわざ一回subjectと書くのが面倒
it do
subject
expect(response.status).to eq 200
end
それに対して、subject(:response)
とするとit
の中でresponse
が呼ばれた時にsubject
の中身が走って、必要な時にgetをやってくれるのでなんだか良いと思ってます。
subject(:response) do
get :index
end
it { expect(response.status).to eq 200 } # responseが呼ばれた時にsubjectのブロックが実行される
というわけでsubject(:response)
ってやっておくとコントローラーのspecを書いてる時の細かい悩みが解決する…気がしてます。
なんかrspec-railsなどの挙動で勘違いしているだろうか。
その他
ここではRailsコントローラーの中でもactionのunitテストを書く場合を考えてます。
Sinatra、Padrinoなどでも同様に出来るとは思いますが実際に試してないです。