DB共有しているRailsアプリケーションのテストを書くときに気をつけること
これで2時間くらい潰れたので供養のために書いておく。
TL;DR
DatabaseCleanerのstrategyがtransactionになってると、もう一方のRailsアプリケーションに反映されないから気をつけよう
遭遇したこと
2つのRailsアプリケーションで1つのDBを共有しているサービスで以下のようなテストを書いていた。
- Rails 2 がレコードを作成する
- Rails 2 がRails1に対して作成したレコードのidを渡しAPI callをする
- Rails 1 が受け取ったidのレコードを取得し、中身を書き換える
- Rails 2 で中身が書き換わったことを確かめる
# めちゃくちゃ雑な図解 Rails 1 Rails 2 | | | a = A.create! | | A.find(a.id) | a.update!(foo: "bar") | | | | expect(a.foo).to eq "bar" | |
実行すると、A.find(a.id)
がResourceNotFoundを返してテストが落ちていた。
テストコードを何回見直してもおかしい箇所は見当たらず、悲しい気持ちになっていたら database_cleanerが悪いことをしている気がしたので確認してみると、
RSpec.configure do |config| ... condig.before do |_| DatabaseCleaner.strategy = :transaction DatabaseCleaner.start end ... end
database_cleanerのstrategyがtransactionに設定されていた。
なので変更してもDB自体にはcommitされていなかったためにRails 1から作成したレコードは見えていなかった。
よく考えると当たり前なんだけど、問題に直面するとなかなか気づかなかったりするのでメモメモ。