我想知道如何在rspec中测试find_each调用。我习惯于简单地存在我希望模型返回的内容,所以我不依赖于db中的测试数据:
MyClass.stub(:find).and_return(my_mock)
但是,在另一个班级我这样做:
MyClass.find_each do |instance_of_my_class|
do_stuff_here_on(instance_of_my_class)
end
我发现如果我这样做:
MyClass.stub(:find_each).and_return([one_mock, two_mock])
在规范测试中,“在这里做东西”部分没有被执行。有谁知道如何为rspec测试存根find_each?
答案 0 :(得分:42)
您可以使用and_yield使rspec调用传递给mock的块:
MyClass.stub(:find_each).and_yield(one_mock).and_yield(two_mock)
答案 1 :(得分:2)
存根方法的全部意义在于该方法返回一个期望值而不执行其内容。如果你在find_each方法中有一堆逻辑,我建议将它移动到一个单独的方法并分别测试该逻辑。然后,您可以测试在执行期间调用您的方法。
这是一个非常高级的例子:
class Example1
def my_method
# some logic
end
end
class Example2
def my_other_method
Example1.find_each(&:my_method)
end
end
Rspec的:
describe Example1 do
it "should return something" do
example = Example1.new
example.my_method.should == something
end
end
describe Example2 do
it "should call my_method on Example1" do
example1 = mock(:example1, :my_method => true)
example2 = Example2.new
example1.should_receive(:my_method)
example2.my_other_method
end
end
答案 2 :(得分:1)
这应该这样做:
MyClass.stub(:find_each) {|block|
block.call
[one_mock, two_mock]
}
如果 do_stuff_here_on 无法全局访问,例如 some_object 上的实例方法,您需要一些instance_eval来获取块的正确范围:
MyClass.stub(:find_each) {|block|
some_object.instance_eval(&block)
[one_mock, two_mock]
}
答案 3 :(得分:0)
如果您需要将find_each
存入经过验证的double并将其循环通过特定的值数组,则可以执行以下操作:
let(:my_relation_with_mocked_find_each) do
relation = instance_double('YourModel::ActiveRecord_Relation')
receive_yield = receive(:find_each)
fake_objs.each do |obj|
receive_yield = receive_yield.and_yield(obj)
end
allow(relation).to receive_yield
relation
end