0

问题

我有一个函数迭代一个关系并在每个成员上调用一个方法:

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

即使调用countActiveRecord::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|,我的规范失败了,我知道代码被破坏了。

4

1 回答 1

0

我会做这样的事情:

let(:foo) { FactoryGirl.create(:foo) }
let(:bar) { double }
let(:array) { [bar] }

before do
  foo.stub(:bars).and_return(array)
end

it 'calls stuff on bar' do
  expect(bar).to receive(:stuff).once
  foo.do_stuff
end

您实际上不需要确保它会被调用foo.bars.count次数,我们可以假设 rubycount​​ 方法正常工作。如果它被调用一次,它也会被调用n多次。

于 2013-10-02T21:25:07.733 回答