Rails / RSpecで例外発生をテストする方法は?


84

次のコードがあります。

def index
    @car_types = car_brand.car_types
end

def car_brand
    CarBrand.find(params[:car_brand_id])
    rescue ActiveRecord::RecordNotFound
        raise Errors::CarBrandNotFound.new 
end

RSpecでテストしたいです。私のコードは:

it 'raises CarBrandNotFound exception' do
    get :index, car_brand_id: 0
    expect(response).to raise_error(Errors::CarBrandNotFound)
end

IDが0のCarBrandが存在しないため、コントローラーコードでErrors :: CarBrandNotFoundが発生しますが、テストコードで何も発生しなかったことがわかります。どうすれば修正できますか?何が間違っていますか?

回答:


115

エラー処理を指定するには、期待値をブロックに設定する必要があります。オブジェクトを評価してもエラーは発生しません。

だからあなたはこのようなことをしたい:

expect {
  get :index, car_brand_id: 0
}.to raise_error(Errors::CarBrandNotFound)

詳細については、予期されるエラーを参照してください。

ただし、仕様の結果に達するまで例外が発生しないことに少し驚いています。


1
@ jakob-sここで使用している予期されるエラー動作は、コントローラー要求では機能しません。get :index, car_brand_id: 0自体ではエラーは発生しません。
リカルドオテロ2015年

@RicardoOtero状況は変わったかもしれませんが、それだけの価値があるので、私にとってはそうです:gist.github.com/koppen/0e1d0894a908a3768847。しかし確かに、スタック内の何かが、スペックランナーにバブルアップする前にエラーを処理している可能性があります。
Jakob S

これは現在のrspecバージョンの正解です。投票する必要があります
Neil Woods

それは正しいです。例外をテストするための正しい形式は、exceptメソッドで()の代わりに{}を使用することです。
ルイスエンリケ2017年

109

expect{}代わりに使用してくださいexpect()


7
{}構文は、発生する特定の例外を監視するブロックを作成するため、これで問題が解決することを指摘しておく価値があります。MiniTestには、コードのブロックで例外が発生することを確認するときに、同様の構文要件があります。
Argus9 2017年

1
そのような小さなダンの変化。しばらくの間、ホイールを磨いてもらいました。これをありがとう。
josh 2017年

4
信じられない。1時間試してみて、それはただ変わっ( )てい{ }ます!どうもありがとうございました
SimonFranzen19年

1
ええ、私のために同じ-私は私が過ごしたと考えているより:)ので、私はここで解決策を掲載していることの
kaleb4eg

2
コメントを使って質問する必要があることはわかっていますが、それでも、回答ありがとうございます。複数のアプローチを経て、ようやく問題の解決策を見つけました。
フローリンレイ

18

get :index 例外が発生することはありません。実際のサーバーと同じように、応答を500エラーに設定します。

代わりに試してください:

it 'raises CarBrandNotFound exception' do
  controller.params[:car_brand_id] = 0
  expect{ controller.car_brand }.to raise_error(Errors::CarBrandNotFound)
end

1
誰かがこれを言ってくれてうれしいです!:)ヤコブは、最も賛成の回答で例外が発生することは決してないことを彼らに教育しようとしましたが、彼はいくつかの誤った抵抗に直面しました。👍
タレクN. Elsamni
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.