使用RSpec时是否有任何方法可以删除任何存根和模拟?
示例:
RestClient.should_receive(:delete).with("http://www.example.com")
...
...
# this will remove the mocking of "should_receive" and
# restore the proper "delete" method on "RestClient".
RestClient.mocking_reset
(mocking_reset
是我所需功能的虚构名称)。
我知道有一个方法“unstub”可以重置“stubs”而不是“should_receive”。
那么,是否有任何方法等同于“unstub”而是“should_receive”?
Panayotis
答案 0 :(得分:39)
您可以通过以下方式覆盖之前的一些模拟:
expect(RestClient).to receive(:delete).and_call_original
或者,如果没有任何期望,只需一个简单的存根:
allow(RestClient).to receive(:delete).and_call_original
请记住,还存在expect_any_instance_of
和allow_any_instance_of
。
答案 1 :(得分:31)
目前(rspec-mocks 2.10.1),没有一种方法等同于unstub
,而是should_receive
。您可以使用rspec_reset
重置所有存根和模拟,也可以编写脏的黑客来删除特定的期望(我不建议这样做)。
以下是删除对象的所有存根和期望的示例:
describe "resetting stubs and expectations with rspec_reset" do
before do
@person = mock('person')
@person.should_receive(:poke)
end
it "should not fail when we reset all stubs and expectations" do
@person.rspec_reset
end
end
请注意,此方法在rspec源代码中注释为@private
,这意味着您应该避免使用它超出绝对必要的范围,并且在未经警告的情况下可能会在未来版本的rspec中中断。然而,它在rspec本身的规范中被广泛使用,所以它似乎不太可能很快被弃用。
在深入研究一下rspec-mocks代码之后,你当然可以做一些非常讨厌的事情并自己撕掉一个特定的期望:
# Works in rspec 2.10.1
describe "removing an expectation with an ugly hack" do
before do
@person = mock('person')
@person.should_receive(:poke)
end
it "should not fail after we hack rspec by violating every law of good programming, ever" do
@person.instance_variable_get(:@mock_proxy).instance_variable_get(:@method_double)[:poke].clear
end
end
这非常糟糕,因为它违反了rspec测试包的封装,你不应该这样做。相反,如果你真的有一个令人信服的理由去除一个特定的期望,那么正确的做法是在rspec-mocks上游添加一个公共方法,为unstub
添加一个并行方法,但是为了消除特定的期望。它可能位于此处(请注意此文件中stub
和unstub
的定义):
https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/methods.rb
在外出并使用上述任何建议消除期望之前,您可能需要考虑您的规格是否真的需要这样做或者是否应该重构。使用should_receive
是关于代码的断言,通常你应该尝试创建只断言一件事的例子(即it
块)。我会非常好奇为什么你需要rspec_reset
这样的东西,除非你试图在全局设置中做太多(例如before :each
或之前:所有块),或者如果你的例子正在尝试做太多(即在一个例子中有多个断言)。
对此的一个例外当然可能是在rspec-mocks的测试套件中,其中rspec_reset
用于在测试应用存根和模拟的功能的示例之间重置状态。除非你这样做,否则很可能你的测试可以改进,不依赖于对象上的存根和模拟的全局重置。
我希望这会有所帮助,如果您认为有一个合法的案例可以向unstub
添加等效方法但是对于消息期望(即,在使用should_receive
之后),请告诉我。 。如果我确信这是一件好事,我会考虑添加这种方法,并建议将其添加到上游。也许它会被称为unset_expectation
?也请随意使用上面的代码和内部结构的指南,自己组合一个rspec-mocks的拉取请求,我们将看看它是否被接受创建一个等同于unstub
的模拟。
答案 2 :(得分:7)
对于RSpec> = 2.14,接受的答案将不再有效。我请你参考BernhardKöhler在这个主题上的答案(转载如下以防止链接腐烂):undefined method `rspec_reset' with rspec version 2.14
RSpec 2.14中不存在重置方法。相反,它是一个帮手 rspec-mocks的spec_helper.rb文件中定义的方法 项目
module VerifyAndResetHelpers def verify(object) RSpec::Mocks.proxy_for(object).verify end def reset(object) RSpec::Mocks.proxy_for(object).reset end end
您可以看到此方法将重置操作委托给 底层代理而不是将其添加到类的定义上 有问题的对象。