Ruby 如何重置模拟类方法的期望值?
如果这很简单,我很抱歉。我对ruby和rspec都是新手,rspec似乎是一个非常“模糊”的世界(尤其是来自.net背景的时候) 在我的“规范”中,我有:Ruby 如何重置模拟类方法的期望值?,ruby,unit-testing,rspec,mocking,Ruby,Unit Testing,Rspec,Mocking,如果这很简单,我很抱歉。我对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_e
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)
这显然没有通过我的测试,因为虽然满足了“不存在.yaml”的预期,但“dummy.yaml”并没有:
但这给了我:
NoMethodError:
undefined method `proxy_for' for RSpec::Mocks:Module
我在文档中找不到这样做的地方,过去的行为表明,这种解决方案在未来也可能会发生变化,但显然,这是您当前可以做到的:
RSpec::Mocks.space.proxy_for(your_object).reset
不过,我会按照@broisasse的说法,考虑重新设计测试,旨在将期望从之前的块中转移出来。正如您所说,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
>P>如果每个测试都应该运行预期,因为每个场景中的变化是上下文,您应该考虑使用:
您可能还想知道是否有更推荐/有文档记录的解决方案来重置模拟对象…这对我从类中卸载特定方法很有效:
mock = RSpec::Mocks.space.proxy_for(MyClass)
mock.instance_variable_get(:@method_doubles)[:my_method].reset
注:逻辑相同
RSpec::Mocks.space.proxy_for(MyClass).reset
重置所有方法在我进行扩展时,我发现我可以使用RSpec::Mocks.space.registered?
检查方法是否为mock,并使用RSpec::Mocks.space.proxy_for(my_mocked_var).reset
重置它的值
这是:
示例:重置模拟值
例如,如果我们想重置这个模拟,它将被取消
默认值,我们可以使用
helper的RSpec::Mocks.space.proxy\u
找到我们的模拟,然后重置它:
# 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
但是请注意,即使重置了模拟值
模拟仍然已注册?
:
RSpec::Mocks.space.registered?(Rails.configuration.action_controller)
# => true
使用“expect_any_instance”时,我成功地使用以下方法更改模拟(例如,我们的示例:发布Twitter帖子并返回不同的tweet id)
期望(Twitter::REST::Client.)的任何实例接收(:update)。并返回(Hashie::Mash.new(id:“12”))
#发布推特
RSpec::Mocks.space.verify\u all
RSpec::Mocks.space.reset_all
期望(Twitter::REST::Client.)的任何实例接收(:update)。并返回(Hashie::Mash.new(id:“12346”))
#再发一条推
您不应在块之前使用预期在中接收。这属于测试。tryRSpec::Mocks.space.proxy_for(您的_对象)。reset
BroiSatse:我假设'before'类似于'[Setup]'(nUnit:.net):不同测试中常见的设置应该放在这里,有助于保持测试干燥,并灵活地进行更改?还是RSpec使用了其他术语来描述我想要实现的目标?@UriAgassi谢谢,这很有效!请你把它作为答案贴出来,这样我就可以接受了。另外,我想知道为什么简单地重置一个mock会有如此繁琐的语法?这不应该是直接的函数调用吗?还是我在试图让RSpec表现得像nUnit(和其他测试框架)?
mock = RSpec::Mocks.space.proxy_for(MyClass)
mock.instance_variable_get(:@method_doubles)[:my_method].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
RSpec::Mocks.space.registered?(Rails.configuration.action_controller)
# => true