我有一个类方法,只需遍历一些记录并在每条记录上执行一个实例方法。我正在尝试为类方法编写一个简单的测试,以确保它将实例方法发送到每个记录。
it "fires any pending alarms" do
pending = create :alarm, :pending
other_pending = create :alarm, :pending
# sanity check
Alarm.pending.sort.should eq [pending, other_pending].sort
pending.should_receive(:fire)
other_pending.should_receive(:fire)
Alarm.fire_pending
end
alarm.rb
class Alarm < ActiveRecord::Base
scope :pending, where(pending: true)
def self.fire_pending
self.pending.each do |alarm|
alarm.fire
end
end
end
但我收到should_receive
期望值的错误:
Failure/Error: pending.should_receive(:fire)
(#<Alarm:0x007fcc96334310>).fire(any args)
expected: 1 time
received: 0 times
我成功地使用了这个期望。我担心我会遗漏一些明显的东西。
修改
我现在已经解决了这个问题:
it "fires any pending alarms" do
pending = create :alarm, :pending
other_pending = create :alarm, :pending
pending_alarms = Alarm.pending
pending_alarms.sort.should eq [pending, other_pending].sort
Alarm.stub(:pending) { pending_alarms }
pending_alarms.first.should_receive(:fire)
pending_alarms.last.should_receive(:fire)
Alarm.fire_pending
end
但我真的不喜欢这样,并且想知道为什么我的第一次尝试不起作用。
答案 0 :(得分:6)
Alarm.pending
返回的对象与示例中创建的对象不同。你可以通过改变:
pending_alarms.sort.should eq [pending, other_pending].sort
为:
# the eq matcher uses == (object equivalence)
# the equal matcher uses equals? (object identity)
pending_alarms.sort.tap do |sorted|
sorted[0].should eq pending # passes
sorted[1].should eq other_pending # passes
sorted[0].should equal pending # fails
sorted[1].should equal other_pending # fails
end
这是使用(邪恶的)any_instance
:
it "fires any pending alarms" do
pending = create :alarm, :pending
Pending.any_instance.should_receive(:fire)
Alarm.fire_pending
end