Ruby 在rspec中分离存根和断言

Ruby 在rspec中分离存根和断言,ruby,rspec,bdd,rspec2,Ruby,Rspec,Bdd,Rspec2,我使用rspec和rspec mocks库进行存根/模拟,但我开始认为存根一个方法和断言它是如何被使用之间的界限是模糊的。在我的测试中,我经常会写下如下内容: before(:each) do subject.should_receive(:sum).once.with([1, 2, 3]).and_return(6) end it("should do something that relies on sum") do subject.call_something([1, 2, 3]

我使用rspec和rspec mocks库进行存根/模拟,但我开始认为存根一个方法和断言它是如何被使用之间的界限是模糊的。在我的测试中,我经常会写下如下内容:

before(:each) do
  subject.should_receive(:sum).once.with([1, 2, 3]).and_return(6)
end

it("should do something that relies on sum") do
  subject.call_something([1, 2, 3]).should == 24
end
但我的主张是什么?那叫什么([1,2,3]):

  • 返回
    24
  • 在执行期间调用sum([1,2,3])
但是,只有一个
it
块-另一个断言隐藏在存根定义中。换句话说,我的存根也是我的断言。将两者分开,并在stubbed方法的调用方式中加入一个明确的断言,不是更清楚吗

before(:each) do
  # set up what my stub should return for a given input
  subject.may_receive(:sum).with([1, 2, 3]).and_return(6)
end

# assert how my stub was actually called
it("should have called sum with 1, 2, 3") do
  # this is pseudo-rspec
  subject.call_something([1, 2, 3]).should have_called(:sum).on(subject).once.with([1, 2, 3])
end
it("should do something that relies on sum") do
  subject.call_something([1, 2, 3]).should == 24
end
这样就很清楚我在断言什么,因为我的存根定义和断言是分开的。我可以在顶部设置测试,然后在底部检查它的行为,而不必将两者混合

所以,我的问题是,是否有办法做到这一点?大多数模拟框架的工作方式与rspec模拟相同,定义存根方法如何与预期行为一起使用的契约,然后在最后自动检查断言


我的观点是关于BDD如何工作的概念性观点,可能有点微妙。让我知道我需要进一步澄清

你说得对
should_receive
是一个断言(更准确地说,它是一个期望),不应该在
块之前进入
。如果您需要
的存根副作用,则应在
之前在
中单独存根:

before do
  subject.stub(:sum).and_return(6)
end

it "should do something that relies on sum" do
  subject.should_receive(:sum).once.with([1, 2, 3]).and_return(6)
  subject.call_something([1, 2, 3]).should == 24
end

这样可以将存根和期望分开,并将它们放在不同的位置。

看起来不错。但是如果我需要使用不同的参数多次调用
sum
,每次得到不同的结果,该怎么办?(这就是我传统上避免使用存根的原因)如果
存根
的返回值发生变化,那么测试应该位于不同的
上下文
块中,在这种情况下,您可以使用
let
s来减少
块之前的
重复。