From ba40c3072f82580401f5c084c5c5736b7f008e85 Mon Sep 17 00:00:00 2001 From: Jon Rowe Date: Sat, 12 Dec 2020 20:20:46 +0000 Subject: [PATCH] Merge pull request #1357 from zhisme/main raise ArgumentError if object cannot be proxied --- lib/rspec/mocks/proxy.rb | 16 ++++++++++++++++ spec/rspec/mocks/space_spec.rb | 16 ++++++++++++++++ .../syntax_agnostic_message_matchers_spec.rb | 12 ++++++++++++ 3 files changed, 44 insertions(+) diff --git a/lib/rspec/mocks/proxy.rb b/lib/rspec/mocks/proxy.rb index 6d3583c5b..d8f092d8c 100644 --- a/lib/rspec/mocks/proxy.rb +++ b/lib/rspec/mocks/proxy.rb @@ -21,6 +21,8 @@ def ensure_implemented(*_args) # @private def initialize(object, order_group, options={}) + ensure_can_be_proxied!(object) + @object = object @order_group = order_group @error_generator = ErrorGenerator.new(object) @@ -31,6 +33,20 @@ def initialize(object, order_group, options={}) @method_doubles = Hash.new { |h, k| h[k] = MethodDouble.new(@object, k, self) } end + # @private + def ensure_can_be_proxied!(object) + return unless object.is_a?(Symbol) || object.frozen? + return if object.nil? + + msg = "Cannot proxy frozen objects" + if Symbol === object + msg << ". Symbols such as #{object} cannot be mocked or stubbed." + else + msg << ", rspec-mocks relies on proxies for method stubbing and expectations." + end + raise ArgumentError, msg + end + # @private attr_reader :object diff --git a/spec/rspec/mocks/space_spec.rb b/spec/rspec/mocks/space_spec.rb index d5d8f5a16..486ec610a 100644 --- a/spec/rspec/mocks/space_spec.rb +++ b/spec/rspec/mocks/space_spec.rb @@ -232,6 +232,22 @@ def create_generations }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /Diff/) end + it 'raises ArgumentError with message if object is symbol' do + space1 = Space.new + object = :subject + expected_message = "Cannot proxy frozen objects. Symbols such as #{object} cannot be mocked or stubbed." + + expect { space1.proxy_for(object) }.to raise_error(ArgumentError, expected_message) + end + + it 'raises ArgumentError with message if object is frozen' do + space1 = Space.new + object = "subject".freeze + expected_message = "Cannot proxy frozen objects, rspec-mocks relies on proxies for method stubbing and expectations." + + expect { space1.proxy_for(object) }.to raise_error(ArgumentError, expected_message) + end + def in_new_space_scope RSpec::Mocks.setup yield diff --git a/spec/rspec/mocks/syntax_agnostic_message_matchers_spec.rb b/spec/rspec/mocks/syntax_agnostic_message_matchers_spec.rb index 057d6e541..d94e1b449 100644 --- a/spec/rspec/mocks/syntax_agnostic_message_matchers_spec.rb +++ b/spec/rspec/mocks/syntax_agnostic_message_matchers_spec.rb @@ -42,6 +42,12 @@ module Mocks reset subject end + + context 'when target cannot be proxied' do + it 'raises ArgumentError with message' do + expect { ::RSpec::Mocks.allow_message(:subject, :foo) { :a } }.to raise_error(ArgumentError) + end + end end RSpec.describe ".expect_message" do @@ -91,6 +97,12 @@ module Mocks verify subject end + + context 'when target cannot be proxied' do + it 'raises ArgumentError with message' do + expect { ::RSpec::Mocks.expect_message(:subject, :foo) { :a } }.to raise_error(ArgumentError) + end + end end end end