问题
我有一个函数迭代一个关系并在每个成员上调用一个方法:
def do_stuff
count = 0
foo.bars.active.each do |bar|
bar.stuff
count += 1
end
count
end
注意:active
是一个bars
返回关系而不是数组的范围。
我的测试看起来像这样:
describe :do_stuff do
let(:foo) { FactoryGirl.create(:foo) }
before { foo.bars << FactoryGirl.create(:bar, :mock_stuff) }
subject { foo }
it { subject.do_stuff.should == 1 }
it "does lots of stuff" do
5.times { subject.bars << FactoryGirl.create(:bar, :mock_stuff) }
subject.do_stuff.should == 6
end
end
酒吧工厂
FactoryGirl.define do
data { random_string }
trait :mock_stuff do
after_build { |bar| bar.stub(:stuff).and_return(true) }
end
end
问题是我实际上并没有验证bar.stuff
是否被调用过。当我试图重构do_stuff
这个时,我烧了自己:
def do_stuff
foo.bars.active.count do |bar|
bar.stuff
end
end
即使调用count
ActiveRecord::Relation 不会执行该块,所有测试仍然通过 :( 我希望before
在我的规范中有一个块来执行以下操作:
before do
foo.bars.each do |bar|
bar.should_receive(:stuff)
end
end
问题是bar
上面返回的实例与代码中实例化的实例不同。
回答
我终于弄明白了。这是失败的规范,当它应该失败并且不会让你担心如果你正在迭代一个数组或一个关系:
describe :do_stuff do
subject { FactoryGirl.create(:foo, :with_bar) }
it "does stuff to bar" do
Bar.any_instance.should_receive(:stuff)
subject.do_stuff
end
end
这里的技巧是你不能let
像我在第一个例子中那样在块中定义 foo 。
富工厂:
FactoryGirl.define do
data { random_string }
trait :with_bar do
after_build do |foo|
foo.bars << FactoryGirl.create(:bar)
end
end
end
现在,当我做一些愚蠢的事情时foo.bars.active.count do |bar|
,我的规范失败了,我知道代码被破坏了。