2012/07/12

[rails] rspecでDBのロールバックをテストする。

Railsアプリで、ActiveRecord::Base.transactionを使って、 トランザクションを明示的に張り、異常がある場合にロールバックする、 という実装は大いに有りますよね。

僕はRSpecを使ってテストしています。
RSpecを使って、DBがロールバックされることを確認する方法を書いておきます。

例えば、コントローラに次のような処理を書いたとします。
モデルの変更後、メールを送信する、という処理で、ここでは、メールの送信に失敗した場合は、 変更をロールバックする、という仕様とします。(その仕様は果たして妥当か?はここでは考えない。)


def save_and_send_mail(model)
  begin
    ActiveRecord::Base.tansaction do
      model.save!
      SomeMailer.something.deliver
    end
  rescue => e
    logger.error(e.message)
    logger.error(e.backtrace)
  end
end

「メールの送信に失敗したら、DBをロールバックする」という振る舞いを確認するために、 実行前後でデータを引っ張り出して比較するというのも出来なくはなさそうですが、
ちょっと面倒に思えます。

なので、「ロールバックする」メソッドが呼ばれることを確認することにました。
この「ロールバックする」メソッドとは、

  • ActiveRecord::Base.connection.rollback_db_transaction
にあたるので、

describe 'some method' do

  before do
    # 前処理
  end

  it "should rollback transaction if fail to send mail." do
    # 送信を失敗させる。
    SomeMailer.stub(:something).and_raise StandardError
    # ロールバック処理が呼ばれること
    ActiveRecord::Base.connection.should_receive(:rollback_db_transaction).once
    # 実行
    @controller.save_and_send_mail(model)
  end

end

というexampleが書けます。
これで、RSpecを使って、簡単にロールバックのテストができます。

0 件のコメント: