rspecのletの注意事項
rspecでletを使うとインスタンス変数を使わずにアクセスできるので便利です。
ただし、注意事項があります。
それは、遅延評価されるということです。
describe 'DELETE #destroy' do let(:contact) do create(:contact, firstname: 'Lawrence', lastname: 'Smith') end it "deletes the contact" do expect{ delete :destroy, id: contact }.to change(Contact,:count).by(-1) end end
上記のテストは失敗します。
原因は、expect{}より前にcontactが出てきていないので、contactを値がないからです。
呼び出されてから初めて作られるのですが、この場合は、その値がまだ存在していないです。
修正するとこうなります。
describe 'DELETE #destroy' do let(:contact) do create(:contact, firstname: 'Lawrence', lastname: 'Smith') end it "deletes the contact" do contact expect{ delete :destroy, id: contact }.to change(Contact,:count).by(-1) end end
これがダサいというのならば、let!を書くこともできます。
let! を使うと example の実行前に let! で定義した値が作られるようになります。
describe 'DELETE #destroy' do let!(:contact) do create(:contact, firstname: 'Lawrence', lastname: 'Smith') end it "deletes the contact" do contact expect{ delete :destroy, id: contact }.to change(Contact,:count).by(-1) end end
遅延評価されるというのが、ポイントです。