很抱歉,如果这很简单。我是ruby以及rspec的新手,似乎rspec是一个非常“模糊”的版本。世界(特别是来自.net背景时)。
在我的规范'中,我有:
before(:each) do
expect(File).to receive(:exist?).with("dummy.yaml").and_return (true)
end
这适用于我的所有'示例',除了我希望它返回false的一个。
expect(File).to receive(:exist?).with("non_existent.yaml").and_return (false)
这显然无法通过我的测试,因为虽然" non_existent.yaml"期望得到满足," dummy.yaml"不是:
(<File (class)>).exist?("dummy.yaml")
expected: 1 time with arguments: ("dummy.yaml")
received: 0 times
那么我怎样才能重置&#39; on&#39; File.exist?&#39; (一个类方法模拟)在我设置它的新期望之前? (...&#34; non_existent.yaml&#34; ..)
我用谷歌搜索了它:RSpec::Mocks.proxy_for(your_object).reset
但是这给了我:
NoMethodError:
undefined method `proxy_for' for RSpec::Mocks:Module
答案 0 :(得分:6)
我在文档中的任何地方都找不到这是你应该怎么做的,过去的行为表明这个解决方案将来也可能会发生变化,但显然这就是你现在可以做到的:
RSpec::Mocks.space.proxy_for(your_object).reset
我会关注@ BroiSatse的评论,并考虑重新设计测试,旨在将期望从before
块移开。正如你所说,before
块用于设置,设置是一个非常奇怪的地方,可以达到预期目的。
我不确定你是如何选择这种设计的,但我可以提出两种可能的选择:
如果测试是微不足道的,并且无论如何都会有效,那么你应该用这个明确的期望创建一个测试,同时将其存入其他测试:
before(:each) do
allow(File).to receive(:exist?).with("dummy.yaml").and_return (true)
end
it "asks if file exists" do
expect(File).to receive(:exist?).with("dummy.yaml").and_return (true)
# do the test...
end
如果期望应该针对每个测试运行,因为每个方案中的更改是上下文,您应该考虑使用shared examples:
shared_examples "looking for dummy.yaml" do
it "asks if file exists" do
expect(File).to receive(:exist?).with("dummy.yaml").and_return (true)
# do the test...
end
end
it_behaves_like "looking for dummy.yaml" do
let(:scenario) { "something which sets the context"}
end
如果有更多推荐/记录的解决方案来重置模拟对象,您可能还需要ask myron ...
答案 1 :(得分:0)
这对我来说是从类中取消特定方法的工作:
mock = RSpec::Mocks.space.proxy_for(MyClass)
mock.instance_variable_get(:@method_doubles)[:my_method].reset
注意:的逻辑相同
RSpec::Mocks.space.proxy_for(MyClass).reset
重置所有方法
答案 2 :(得分:0)
在@Uri Agassi's answer和我answered on another similar question的基础上进行扩展,我发现我可以使用RSpec::Mocks.space.registered?
来检查某个方法是否为模拟方法,并可以使用RSpec::Mocks.space.proxy_for(my_mocked_var).reset
来重置其值。
这里是the example I included in my other answer:
示例:重置模拟值
例如,如果我们想
reset
将此模拟恢复为未模拟 默认值,我们可以使用RSpec::Mocks.space.proxy_for
帮助程序 找到我们的模拟,然后reset
:# when # Rails.configuration.action_controller.allow_forgery_protection == false # and # allow(Rails.configuration.action_controller).to receive(:allow_forgery_protection).and_return(true) RSpec::Mocks.space.registered?(Rails.configuration.action_controller) # => true Rails.configuration.action_controller.allow_forgery_protection # => true RSpec::Mocks.space.proxy_for(Rails.configuration.action_controller).reset Rails.configuration.action_controller.allow_forgery_protection # => false
但是请注意,即使已重置模拟值, 模拟遗物
registered?
:RSpec::Mocks.space.registered?(Rails.configuration.action_controller) # => true
答案 3 :(得分:0)
使用“expect_any_instance”时,我使用以下方法成功更改了模拟(例如,我们的示例:发布 Twitter 帖子并返回不同的推文 ID)
expect_any_instance_of(Twitter::REST::Client).to receive(:update).and_return(Hashie::Mash.new(id: "12"))
# post tweet
RSpec::Mocks.space.verify_all
RSpec::Mocks.space.reset_all
expect_any_instance_of(Twitter::REST::Client).to receive(:update).and_return(Hashie::Mash.new(id: "12346"))
# post another tweet