はじめに
rspecのletとlet!の違いを忘れてしまうことが多いのでここにメモする
問題
letとlet!はRSpecのヘルパーメソッドで、テスト内で使用するデータを定義するために使われます。しかし、それらはいつデータが生成されるかという点で違いがあります。
このような場合はcourseが複数保存されている必要があるのでlet!で定義しないとなにも保存されていない状態になります。
get "/api/v1/courses"
expect(JSON.parse(response.body)[0]["authority"]).to eq(course.authority)
expect(JSON.parse(response.body)[0]["travel_mode"]).to eq(course.travel_mode)
expect(JSON.parse(response.body)[1]["authority"]).to eq(other_course.authority)
expect(JSON.parse(response.body)[1]["travel_mode"]).to eq(other_course.travel_mode)
解決方法
- let: letは遅延評価(lazy evaluation)を行います。つまり、letで定義したデータはそのデータが最初に呼び出されたときに初めて生成されます。同一のスコープ内で複数回呼び出された場合でも、データは一度だけ生成されます。
let(:course) { FactoryBot.create(:course) }
- let!: let!は即時評価を行います。つまり、let!で定義したデータは各テストケースが実行される前に必ず生成されます。これは、テストケースが実行される前にデータが存在することを保証する必要がある場合に便利です。
let!(:course) { FactoryBot.create(:course) }
おわりに
よく忘れやすいのでメモしました。