在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