在我的实际操作的简化示例中,假设我有2次调用数据库:
Repo.add( something_stringy )
Repo.remove( something_floaty )
我希望使用mocks进行数据库调用,因为真正的调用将在别处进行测试:
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
因为如果我写了一个接收transaction
的模拟器,它将接收到该调用,但是块中的所有内容都不会被调用,我得到:
预计:1次 收到:0次
所有其他嘲笑。有人能告诉我如何编写我的规范来处理这个问题吗?我已经尝试在around(:each)
上阅读RSpec书中的相关页面了,但这对我来说非常明显。
非常感谢任何帮助。
答案 0 :(得分:12)
您可以使用#and_yield
从预期链中获益:
repo.should_receive( :transaction ).and_yield
您也不需要在Repo类上设置双重存根方法。例如,您的设置可以写成:
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
您也可以考虑使用stub
代替should_receive
,因为它没有设定期望:
before( :each ) do
Repo.stub( :transaction ).and_yield
Repo.stub( :add )
Repo.stub( :remove )
end
通常,只有在想要测试两个对象之间的交互时才应使用should_receive
。我个人的经验法则是,如果它出现在before
中,请使用stub
;如果它是一个示例,特别是具有特定值,请使用should_receive
。