RSpecでrun_callbacks(:commit)が動かない

技術ネタもこちらで書くことにしました!


みなさんはテストを書いていますか?今回は先日RSpecでテストを書いている時に起こったafter_commitが動かないという問題についての内容となっています。

実行環境

  • rails 4.2.10
  • rspec-rails 3.5.2

RSpecのafter_commitのテストで問題発生

先日、RSpecでafter_commitのテストしようと以下のようなコードを書いたのですが思った通りの結果になりませんでした。

どうにも原因がわからずGoogleで調べてみると、use_transactional_fixturesがtrueとなっているとcommitが行われず、一つ一つのexampleがtransaction内で実行され、テスト後にはロールバックされるようになるということです。

ちなみにRSpecのuse_transactional_fixturesはそのままRails側の設定に渡されるようになっています。

https://github.com/rspec/rspec-rails/blob/v3.5.2/lib/rspec/rails/fixture_support.rb#L25-L30

## 強制的にcommitを実行して問題解決

ではどうやってcommitさせるかというと保存処理をしたあとに強制的にtransaction情報をクリアして、そのあとにrun_callbacksというメソッドを使ってcommitを実行させます。

これでafter_commitが正常に動作し無事テストが通るようになりました。

https://stackoverflow.com/questions/33940268/after-commit-callback-on-update-doesnt-trigger を参考に最初はmodel.send(:clear_transaction_record_state)を試してみたのですがうまくいきませんでした。

Railsのコードを読んでみるとどうやらclear_transaction_record_stateだとtransaction情報がうまくクリアされておらず、正しくはforce_clear_transaction_record_stateを呼び出す必要がありました。

https://github.com/rails/rails/blob/v4.2.10/activerecord/lib/active_record/transactions.rb#L379-L388

まとめ

それぞれの設定の意味を理解することはとても大事です。恥ずかしながら今回はそれが出来ていなかったために遭遇した問題でした。

みなさんもデフォルトのままで特に気にしていなかった設定を見返してみるのもいいかもしれません。

スポンサードリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です