繁体   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