Ruby 用RSpec包块的试验方法

Ruby 用RSpec包块的试验方法,ruby,mocking,block,rspec2,Ruby,Mocking,Block,Rspec2,在我实际操作的简化示例中,假设我有2个对数据库的调用: Repo.add( something_stringy ) Repo.remove( something_floaty ) 我想对数据库调用使用mock,因为真正的调用将在其他地方进行测试: let(:repo){ repo = double("Repo") repo.should_receive(:add).with(instance_of(String)) repo.should_receive(:remove).with

在我实际操作的简化示例中,假设我有2个对数据库的调用:

Repo.add( something_stringy )
Repo.remove( something_floaty )
我想对数据库调用使用mock,因为真正的调用将在其他地方进行测试:

let(:repo){
  repo = double("Repo")
  repo.should_receive(:add).with(instance_of(String))
  repo.should_receive(:remove).with(instance_of(Float))
  repo
}

before { FakeKlass.const_set :Repo, repo }
这一切都很好,但现在如果我把电话打包成一个交易,我有点不知所措:

Repo.transaction do
  # ... some error checking in here somewhere...
  Repo.add( something_stringy )
  Repo.remove( something_floaty )
end
因为如果我编写一个接收
事务的模拟,它将接收调用,但块中的所有内容都不会被调用,我得到:

预计:1次 收到:0次

对于所有其他的嘲弄。有人能告诉我应该如何编写规范来处理这个问题吗?我试着阅读RSpec书籍中关于(:each)
的相关页面,但对我来说,这是非常清楚的

非常感谢您的帮助。

您可以使用
#和_yield
从期望链中获得收益:

repo.should_receive( :transaction ).and_yield
您也不需要在Repo类上设置double-to-stubout方法。例如,您的设置可以编写为:

before( :each ) do
    Repo.should_receive( :transaction ).and_yield
    Repo.should_receive( :add ).with( instance_of(String) )
    Repo.should_receive( :remove ).with( instance_of(Float) )
end

您也可以考虑使用<代码>存根而不是<代码> SubddRead < /C> >,因为它没有设置期望:

before( :each ) do
    Repo.stub( :transaction ).and_yield
    Repo.stub( :add )
    Repo.stub( :remove )
end

通常,当您想要测试两个对象之间的交互时,您应该只使用
should\u receive
。我个人的经验法则是,如果它出现在
之前的
中,请使用
存根
;如果它在一个示例中,特别是具有特定值,请使用
should\u receive

谢谢,这也有助于我测试Redis.pipelined wrapped代码,它的行为与事务类似。