在RSpec中如何说“any_instance”“should_receive”任意次数
我有一个导入控制器导入几个CSV文件到我的数据库的多个logging。 我想在RSpec中进行testing,如果使用RSpec实际保存logging:
<Model>.any_instance.should_receive(:save).at_least(:once)
不过,我得到的错误说:
The message 'save' was received by <model instance> but has already been received by <another model instance>
控制器的一个人为的例子:
rows = CSV.parse(uploaded_file.tempfile, col_sep: "|") ActiveRecord::Base.transaction do rows.each do |row| mutation = Mutation.new row.each_with_index do |value, index| Mutation.send("#{attribute_order[index]}=", value) end mutation.save end
有没有可能使用RSpec来testing这个,或者是否有任何解决方法?
有一个新的语法:
expect_any_instance_of(Model).to receive(:save).at_least(:once)
这是一个更好的答案,可以避免重写:new方法:
save_count = 0 <Model>.any_instance.stub(:save) do |arg| # The evaluation context is the rspec group instance, # arg are the arguments to the function. I can't see a # way to get the actual <Model> instance :( save_count+=1 end .... run the test here ... save_count.should > 0
似乎stub方法可以被附加到没有约束的任何实例上,并且do块可以进行一个计数,你可以检查以确定它被称为正确的次数。
更新 – 新的rspec版本需要以下语法:
save_count = 0 allow_any_instance_of(Model).to receive(:save) do |arg| # The evaluation context is the rspec group instance, # arg are the arguments to the function. I can't see a # way to get the actual <Model> instance :( save_count+=1 end .... run the test here ... save_count.should > 0
我终于设法做了一个适合我的testing:
mutation = FactoryGirl.build(:mutation) Mutation.stub(:new).and_return(mutation) mutation.should_receive(:save).at_least(:once)
存根方法返回多次接收存储方法的单个实例。 因为它是一个单一的实例,我可以删除any_instance
方法,并正常使用at_least
方法。
存根这样
User.stub(:save) # Could be any class method in any class User.any_instance.stub(:save) { |*args| User.save(*args) }
然后期望像这样:
# User.any_instance.should_receive(:save).at_least(:once) User.should_receive(:save).at_least(:once)
这是这个要点的简化,使用any_instance
,因为你不需要代理原来的方法。 参考这个要点用于其他用途。
这是Rob使用RSpec 3.3的例子,它不再支持Foo.any_instance
。 我发现这在循环创build对象时很有用
# code (simplified version) array_of_hashes.each { |hash| Model.new(hash).write! } # spec it "calls write! for each instance of Model" do call_count = 0 allow_any_instance_of(Model).to receive(:write!) { call_count += 1 } response.process # run the test expect(call_count).to eq(2) end
我的情况有点不同,但是我最终在这个问题上想到了我的答案。 在我的情况下,我想存根一个给定类的任何实例。 当我使用expect_any_instance_of(Model).to
时遇到了同样的错误。 当我将其更改为allow_any_instance_of(Model).to
,我的问题就解决了。
查看更多背景的文档: https : //github.com/rspec/rspec-mocks#settings-mocks-or-stubs-on-any-instance-of-a-class