2017-10-10 69 views
0

我有以下代碼,並測試我似乎無法通過。該代碼應自動鎖定24小時前完成的所有預訂。Rails Rspec測試失敗,當它在應用程序中工作

當我將pry放入測試並運行Booking.auto_lock_guests的第一行時,沒有任何反應。當我輸入booking_7並輸入Booking.auto_lock_guests之後,它將鎖定爲true。這是否與let的設置方式有關,它不會顯示在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 

回答

0

我最後不得不打電話Booking.auto_lock_guests後動作之前加入到這一點,它的工作。

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

我很困惑這是如何工作的,因爲我確信在調用Booking.auto_lock_guests時兩個預訂都沒有被創建,但是如果它可以工作,它就可以工作。 – Magnuss

1

let被懶惰地評價。當before塊被執行時,沒有記錄,因爲let塊尚未被調用。

要麼改變letlet!立即執行塊或致電booking_6booking_7Booking.auto_lock_guests前右

編輯:

而且你不請檢查是否booking.save成功。如果booking.save失敗 - 你永遠不會知道。 :)

next unless booking.guests_completed_at <= 1.day.ago很可能被改寫爲查詢:where(Booking.arel_table[:guests_completed_at].gt(1.day.ago))

+0

這似乎沒有解決它,但我現在已經解決了這個問題。感謝關於檢查保存的提示。我現在補充說。 – Georgeheap

1

您不需要首先遍歷記錄。事實上,由於將所有這些記錄拉入內存將會消耗服務器(或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 

一次許多單獨的更新查詢和更新多行之間在執行時間上的差異可能是巨大的。

爲了測試它,你可以創建多個記錄,並利用變化的預期:

# 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是一個非常好的主意測試一個改變,因爲他們同時驗證初始狀態和結果的數據庫方法時。

+0

如果您確實需要將記錄從數據庫中提取出來,請確保您[批量]執行此操作(http://api.rubyonrails.org/v5.1/classes/ActiveRecord/Batches.html)。 – max

+0

當用戶登錄時,'context'應該用於上下文環境''。應使用'describe'塊來描述你正在測試的內容。 – max

+0

我正在做一些事情後,我沒有列出這部分工作的預訂。我肯定會改變它,因爲這會限制通過的預訂數量。但我不認爲我可以做update_all,因爲我似乎失去了一系列預訂,然後在預訂中找不到客人。 – Georgeheap