のえら

技術備忘とかメモとか.間違いはつっこんでいただきたい所存.アフィリエイトはやっていません.

Rspecの呼び出し回数チェックテストで全件通し実行するとコケていた件

rspecでrake task系のユニットテストで、onceなどのメソッド呼び出し回数チェックを使用していた。
それらのユニットテストをそれ単体で実行すると成功するが、テストを通して全件実行すると失敗する。
検証したところ、spec/lib/tasks/xxx_spec.rb で以下のようにrake taskを呼び出すためにロードしているが、 Rake::Task[task_name].invoke がこのコードを読み込んだ回数分、指定のタスクを実行していた。

before(:all) do
  Rails.application.load_tasks
end

このため、同様のrake task系テストをまとめているディレクトリ配下のユニットテストを通しで実行すると、回数を検証するonceなどを使用しているitブロックで複数回rake叩いた挙動になってしまい、テストに失敗する。

例)
spec/aaa_task_spec.rb

before(:all) do
  Rails.application.load_tasks
end

context 'HogeClass#foo' do
  it { expect(HogeClass).to receive(:foo).once.with(kind_of(RuntimeError)) }
end

spec/bbb_task_spec.rb

before(:all) do
  Rails.application.load_tasks
end

context 'FugaClass#foo' do
  it { expect(FugaClass).to receive(:foo).once.with(kind_of(RuntimeError)) }
end

spec/ccc_task_spec.rb

before(:all) do
  Rails.application.load_tasks
end

context 'HogeClass#foo' do
  it { expect(HogeClass).to receive(:foo).once.with(kind_of(RuntimeError)) }
end

rspec spec/

  • > 1) HogeClass#foo

Failure/Error: expect(HogeClass).to receive(:foo).once.with(kind_of(RuntimeError))

(HogeClass (class)).foo(kind of RuntimeError)
expected: 1 time with arguments: (kind of RuntimeError)
received: 2 times
...

※load_tasksを呼び出す回数ずつ増える

解決策の例

1)各ファイルでのタスク読み込みをやめてspec_helperなどで一回だけ呼ぶようにする
2)タスク読み込みをまとめて行うのではなく、都度Rake.application.rake_requireする

rails_helperにて一回だけ呼ぶように変更