Rails Rspec测试在app中运行时失败

时间:2017-10-10 06:45:27

标签: ruby-on-rails ruby rspec

我有以下代码和测试,我似乎无法通过。代码应该是自动锁定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

3 个答案:

答案 0 :(得分:1)

let被懒惰地评估了。当before块被执行时,没有记录,因为尚未调用let块。

let更改为let!以立即执行阻止,或者在booking_6之前调用booking_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))

答案 1 :(得分: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

许多单独的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是一个非常好的主意,因为它们会验证初始状态和结果。

答案 2 :(得分:0)

在调用Booking.auto_lock_guests之后,我最终不得不将其添加到之前的操作中。它有效。

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