6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Railsのコントローラーのspecを書くとき、subject(:response)と書いてみる

Posted at

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などでも同様に出来るとは思いますが実際に試してないです。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?