diff --git a/Changelog.md b/Changelog.md index a16665007..d15e690f2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -26,6 +26,8 @@ Bug fixes when the wrong number of args are passed (Jon Rowe). * Fix `double` on 1.9.2 so you can wrap them in an Array using `Array(my_double)` (Jon Rowe). +* Fix `stub_const` and `hide_const` to handle constants that redefine `send` + (Sam Phippen). Deprecations diff --git a/lib/rspec/mocks/mutate_const.rb b/lib/rspec/mocks/mutate_const.rb index 174ea97cf..cc0ecf5cb 100644 --- a/lib/rspec/mocks/mutate_const.rb +++ b/lib/rspec/mocks/mutate_const.rb @@ -225,7 +225,7 @@ def mutate @context = recursive_const_get(@context_parts.join('::')) @original_value = get_const_defined_on(@context, @const_name) - @context.send(:remove_const, @const_name) + @context.__send__(:remove_const, @const_name) end def to_constant @@ -251,7 +251,7 @@ def mutate constants_to_transfer = verify_constants_to_transfer! - @context.send(:remove_const, @const_name) + @context.__send__(:remove_const, @const_name) @context.const_set(@const_name, @mutated_value) transfer_nested_constants(constants_to_transfer) @@ -266,7 +266,7 @@ def to_constant end def rspec_reset - @context.send(:remove_const, @const_name) + @context.__send__(:remove_const, @const_name) @context.const_set(@const_name, @original_value) end @@ -336,7 +336,7 @@ def to_constant end def rspec_reset - @deepest_defined_const.send(:remove_const, @const_to_remove) + @deepest_defined_const.__send__(:remove_const, @const_to_remove) end end diff --git a/spec/rspec/mocks/mutate_const_spec.rb b/spec/rspec/mocks/mutate_const_spec.rb index af4b83dad..b2abe8371 100644 --- a/spec/rspec/mocks/mutate_const_spec.rb +++ b/spec/rspec/mocks/mutate_const_spec.rb @@ -12,6 +12,13 @@ class NestedEvenMore end end +class TestClassThatDefinesSend + C = :c + + def self.send + end +end + class TestSubClass < TestClass P = :p end @@ -46,7 +53,7 @@ def reset_rspec_mocks after { change_const_value_to(original_const_value) } def change_const_value_to(value) - parent_const.send(:remove_const, last_const_part) + parent_const.__send__(:remove_const, last_const_part) parent_const.const_set(last_const_part, value) end @@ -143,6 +150,11 @@ def change_const_value_to(value) end describe "#hide_const" do + context "for a loaded constant nested in a module that redefines `send`" do + it_behaves_like "loaded constant hiding", "TestClassThatDefinesSend::C" + end + + context 'for a loaded nested constant' do it_behaves_like "loaded constant hiding", "TestClass::Nested" end @@ -205,6 +217,10 @@ def change_const_value_to(value) end describe "#stub_const" do + context "for a loaded constant nested in a module that redefines `send`" do + it_behaves_like "loaded constant stubbing", "TestClassThatDefinesSend::C" + end + context 'for a loaded unnested constant' do it_behaves_like "loaded constant stubbing", "TestClass" @@ -309,6 +325,10 @@ def change_const_value_to(value) it_behaves_like 'unloaded constant stubbing', "::SomeUndefinedConst" end + context "for an unloaded constant nested in a module that redefines `send`" do + it_behaves_like 'unloaded constant stubbing', "TestClassThatDefinesSend::SomeUndefinedConst" + end + context 'for an unloaded constant with nested name that matches a top-level constant' do it_behaves_like "unloaded constant stubbing", "TestClass::Hash" end