簡體   English   中英

在應用程序中運行時,Rails Rspec測試失敗

[英]Rails Rspec test fails when it works in app

我有以下代碼並測試似乎無法通過。 該代碼應自動鎖定所有在24小時前完成的預訂。

當我撬入測試並運行Booking.auto_lock_guests的第一行時,什么都沒有發生。 當我輸入booking_7並在輸入Booking.auto_lock_guests之后,它將更改為true。 這與讓設置未在Booking.all中顯示的方式有關嗎? 還是我編寫測試的方式?

任何幫助將不勝感激。

  def self.auto_lock_guests
    bookings = Booking.where(guests_completed: true, locked: false)
    bookings.each do |booking|
      next unless booking.guests_completed_at <= 1.day.ago
      booking.locked = true
      booking.save
    end
  end


  context 'auto_lock_guests' do
    let(:booking_6) { FactoryGirl.create(:booking, date: Date.today - 5.day, guests_completed: true, guests_completed_at: DateTime.now, locked: false )}
    let(:booking_7) { FactoryGirl.create(:booking, date: Date.today - 5.day, guests_completed: true, guests_completed_at: DateTime.now - 3.day, locked: false )}
    before do
      Booking.auto_lock_guests
    end
    it 'should only lock bookings with a guests_completed date older than a day ago' do
      expect(booking_7.locked).to eq(true)
      expect(booking_6.locked).to eq(false)
    end
  end

let被懶惰地評估。 執行before塊時,沒有記錄,因為還沒有調用let塊。

要么改變let let! 立即執行區塊或在Booking.auto_lock_guests之前Booking.auto_lock_guests致電booking_6booking_7

編輯:

另外,您不檢查booking.save是否成功。保存成功。 如果booking.save失敗-您將永遠不會知道。 :)

next unless booking.guests_completed_at <= 1.day.ago可以重寫為查詢: where(Booking.arel_table[:guests_completed_at].gt(1.day.ago))

您無需首先遍歷記錄。 實際上,這將在您的應用擴展時引起問題,因為將所有這些記錄拉入內存將耗盡服務器(或dynos)的內存。

您可以從數據庫中選擇記錄,並在單個查詢中更新它們:

class Booking
  def self.auto_lock_guests!
    bookings = Booking.where(guests_completed: true, locked: false)
                      .where('guests_completed_at <= ?', 1.day.ago)
    bookings.update_all(locked: true)
  end
end

許多單獨的UPDATE查詢與一次更新許多行之間的執行時間差異可能很大。

要測試它,您可以創建多個記錄並使用更改期望:

# use describe and not context for methods.
describe ".auto_lock_guests" do
  # let! is not lazy loading
  let!(:old_booking) { FactoryGirl.create(:booking, date: 7.days.ago, guests_completed: true, guests_completed_at: 3.days.ago, locked: false )}
  let!(:new_booking) { FactoryGirl.create(:booking, date: Date.today, guests_completed: true, guests_completed_at: DateTime.now, locked: false )}

   it 'locks a booking with a guests_completed date older than a day ago' do
     expect do
       Bookings.auto_lock_guests! && old_booking.reload
     end.to change { old_booking.locked }.from(false).to(true)
   end

   it 'does not lock a when guests_completed date is less than a day ago' do
     expect do
       Bookings.auto_lock_guests! && new_booking.reload
     end.to_not change { new_booking.locked }.from(false).to(true)
   end
end

在測試更改數據庫的方法時,使用change是一個好主意,因為這些方法可以驗證初始狀態和結果。

我最終不得不在調用Booking.auto_lock_guests之后將其添加到before操作中,並且可以正常工作。

before do
  Booking.auto_lock_guests
  booking_7.reload
  booking_6.reload
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM