主要用于测试调试目的,我想知道是否有办法判断方法是否存在。
例如,在我的一个测试中,我写道:
Model.any_instance.stub(:method)
当我有一个真实的实例时,我想写一些类似的东西:
an_instance_of_model.stubbed?(:method) # expecting to return true
答案 0 :(得分:2)
如果您使用any_instance
方法在类级别中隐藏了方法,您可以在测试中使用以下内容检查:
RSpec::Mocks.any_instance_recorder_for(YourClass).already_observing?(:method_name)
但如果你存根特定的实例,你可以使用以下方法找到它:
!(your_instance.method(:method_name).owner >= your_instance.class)
所以你也可以在辅助模块中组合这些:
module Helpers
def stubbed?(object, method)
RSpec::Mocks.any_instance_recorder_for(object.class).already_observing?(method) || !(object.method(method).owner >= object.class)
end
end
并将其包含在RSpec.configure中:
require 'helpers'
RSpec.configure do |config|
...
config.include Helpers
...
end
答案 1 :(得分:0)
在doesn't appear to be documented very well之后,从@PJSCopeland's comment开始,看来您可以使用RSpec::Mocks.space.registered?
检查是否存在“模拟代理”:
# eg. allow(Rails.configuration.action_controller).to receive(:allow_forgery_protection).and_return(true)
RSpec::Mocks.space.registered?(Rails.configuration.action_controller)
# => true
RSpec::Mocks.space.registered?(Rails.configuration)
# => false
在撬调试会话中,我们可以看到:
ls RSpec::Mocks
# => RSpec::Mocks.methods: allow_message configuration error_generator expect_message setup space teardown verify with_temporary_scope
ls RSpec::Mocks.space
# => RSpec::Mocks::Space#methods: any_instance_mutex any_instance_proxy_for any_instance_recorder_for any_instance_recorders any_instance_recorders_from_ancestry_of constant_mutator_for ensure_registered new_scope proxies proxies_of proxy_for proxy_mutex register_constant_mutator registered? reset_all superclass_proxy_for verify_all
查看https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/space.rb#L127-L129,我们可以看到registered?
检查了proxies.key?
,其中proxies
是RSpec::Space
类的attr:
module RSpec
module Mocks
# ..snip..
class Space
attr_reader :proxies, :any_instance_recorders, :proxy_mutex, :any_instance_mutex
# ..snip..
def registered?(object)
proxies.key?(id_for object)
end
# ..snip..
end
end
end
撬起,我们可以看到proxies
是一个Hash
,它将一个ID号(由id_for
创建)映射到表示该模拟的RSpec::Mocks::Proxy
实例:>
RSpec::Mocks.space.proxies.class
# => Hash
RSpec::Mocks.space.proxies.map { |k,v| v.class }
# => [RSpec::Mocks::PartialClassDoubleProxy, RSpec::Mocks::PartialDoubleProxy]
从可用方法中可以看到,如果我们愿意,这将使我们有很深的机会来玩模拟游戏:
ls RSpec::Mocks.space.proxies.map { |k,v| v }.first
# RSpec::Mocks::Proxy#methods: add_message_expectation add_stub as_null_object build_expectation check_for_unexpected_arguments ensure_implemented has_negative_expectation? messages_arg_list method_double_if_exists_for_message null_object? object prepended_modules_of_singleton_class raise_missing_default_stub_error raise_unexpected_message_error received_message? record_message_received remove_stub remove_stub_if_present replay_received_message_on verify
# RSpec::Mocks::PartialDoubleProxy#methods: add_simple_expectation add_simple_stub message_received reset visibility_for
# RSpec::Mocks::PartialClassDoubleProxyMethods#methods: original_method_handle_for
例如,如果我们想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