RSpec で例外テストの書き方、および ActiveRecord の例外をテストする際の注意

昨日のエントリー、Rails モデルの RSpec 単体テストで validation と DB に対するテストを区別した | EasyRamble の補足エントリーになります。

スポンサーリンク

— 環境 —
rails-4.0.1
rspec-rails-2.14.0
capybara-2.2.0

RSpec で例外をテストするコード

unique キー制約の付いていてるDBカラムに対して、以下のように例外の発生を確認するテストを書いたのですが、この時はまった箇所がありました。

spec/models/user_spec.rb

User モデルについて、email カラムが DB で unique 制約となっています。なので、既存のユーザーと email が同一のユーザーを保存しようとしたら、例外(ActiveRecord::RecordNotUnique)が発生することを意図して書いたテストコードです。このテストコードは、正しく動作します。

save と save! は違う

【追記 2014/12/08】
Rails勉強中さんにコメントを頂きまして、このパラグラフの記述が間違っていることに気付きましたので訂正します。save メソッドでも ActiveRecord::RecordNotUnique は raise され、save メソッドでは ActiveRecord::RecordInvalid のエラーだけが rescue されて false を返しているとのことです。なので、この記事内の ActiveRecord::RecordNotUnique の例外捕捉のテストでは、save! ではなく save を使っても構いません。Rails のソースコードを確認したところ、確かにそうなっていました。

save (ActiveRecord::Persistence) – APIdock

以降このパラグラフの間違えていた文章は、打ち消し線で訂正しておきます。Rails勉強中さん、ご指摘ありがとうございました!
【追記ここまで】

の行についてなのですが、最初以下のように書いていました。

save メソッドは、レコード保存に失敗しても false を返すだけです。なので、何の例外も発生させず、以下のようにテストを通らず。

レコード保存の失敗時に例外を返すためには、感嘆符付きの save! メソッドを使う必要があります。

validation のスキップには validate: false

上記コードを書いてテストを行ってみましたところ、次のエラー。

User モデルに書いてある validation に引っかかってしまい、DB に保存するところまで行ってません。なので、validation を無効にする必要がある。

ということで、最終的に以下のように変更。

これで、意図した通りに、ActiveRecord::RecordNotUnique を発生させるテストを実行できました。

スポンサーリンク
私は Rails のテストフレームワークには RSpec を使っています。サーバーのテスト用に Serverspec もおすすめです。
スポンサーリンク
 
Twitterを使っていますのでフォローお願いたします!ブログの更新情報もつぶやいてます^^
(英語学習用)
  • 2件のコメント
  • Rails勉強中

    saveでもActiveRecord::RecordNotUniqueはraiseされますよん。

    saveメソッドがrescueでfalse返しているのは、ActiveRecord::RecordInvalidのエラーだけなので。

    データベースエラーやBugなのでraiseされた場合は、rescueされまえん

    • taka

      Rails勉強中さん、ご指摘ありがとうございます。訂正いたしました。

Leave Your Message!