From 273f50bffde242c21ef5dfac2212f95f58b22f0d Mon Sep 17 00:00:00 2001 From: Xavier Shay Date: Wed, 5 Mar 2014 20:23:49 -0800 Subject: [PATCH] Deprecate non-opt-in Marshal monkey-patch. --- Changelog.md | 1 + lib/rspec/mocks/configuration.rb | 9 +++++++++ lib/rspec/mocks/extensions/marshal.rb | 15 +++++++++++++++ spec/rspec/mocks/extensions/marshal_spec.rb | 8 ++++++++ spec/rspec/mocks/serialization_spec.rb | 2 ++ 5 files changed, 35 insertions(+) diff --git a/Changelog.md b/Changelog.md index f86fa0ee8..0aeea4df0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Deprecations: * Deprecate `RSpec::Mocks::TestDouble.extend_onto`. (Myron Marston) * Deprecate `RSpec::Mocks::ConstantStubber`. (Jon Rowe) +* Deprecate `Marshal.dump` monkey-patch without opt-in. (Xavier Shay) ### 2.99.0.beta2 / 2014-02-17 [full changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.0.beta1...v2.99.0.beta2) diff --git a/lib/rspec/mocks/configuration.rb b/lib/rspec/mocks/configuration.rb index de60d0bfd..b7f5fda56 100644 --- a/lib/rspec/mocks/configuration.rb +++ b/lib/rspec/mocks/configuration.rb @@ -6,6 +6,7 @@ class Configuration def initialize @yield_receiver_to_any_instance_implementation_blocks = false @should_warn_about_any_instance_blocks = true + @marshal_patched = false end def yield_receiver_to_any_instance_implementation_blocks? @@ -62,6 +63,14 @@ def syntax syntaxes << :expect if Syntax.expect_enabled? syntaxes end + + def patch_marshal_to_support_partial_doubles=(val) + @marshal_patched = val + end + + def marshal_patched? + @marshal_patched + end end def self.configuration diff --git a/lib/rspec/mocks/extensions/marshal.rb b/lib/rspec/mocks/extensions/marshal.rb index b8cf7b5df..2157256c3 100644 --- a/lib/rspec/mocks/extensions/marshal.rb +++ b/lib/rspec/mocks/extensions/marshal.rb @@ -6,6 +6,21 @@ def dump_with_mocks(object, *rest) if ::RSpec::Mocks.space.nil? || !::RSpec::Mocks.space.registered?(object) || NilClass === object dump_without_mocks(object, *rest) else + unless ::RSpec::Mocks.configuration.marshal_patched? + RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\|/, '')) + |Using Marshal.dump on stubbed objects relies on a monkey-patch + |that is being made opt-in in RSpec 3. To silence this warning + |please explicitly enable it: + | + |RSpec.configure do |rspec| + | rspec.mock_with :rspec do |mocks| + | mocks.patch_marshal_to_support_partial_doubles = true + | end + |end + | + |Called from #{RSpec::CallerFilter.first_non_rspec_line}." + EOS + end dump_without_mocks(object.dup, *rest) end end diff --git a/spec/rspec/mocks/extensions/marshal_spec.rb b/spec/rspec/mocks/extensions/marshal_spec.rb index 46f436b34..3d2514e51 100644 --- a/spec/rspec/mocks/extensions/marshal_spec.rb +++ b/spec/rspec/mocks/extensions/marshal_spec.rb @@ -31,13 +31,21 @@ def without_space end context 'when rspec-mocks has been fully initialized' do + include_context 'with isolated configuration' + it 'duplicates objects with stubbed or mocked implementations before serialization' do + RSpec::Mocks.configuration.patch_marshal_to_support_partial_doubles = true obj = double(:foo => "bar") serialized = Marshal.dump(obj) expect(Marshal.load(serialized)).to be_an(obj.class) end + it 'provides a deprecation warning' do + expect_warn_deprecation_with_call_site('marshal_spec.rb', __LINE__ + 1) + Marshal.dump double(:foo => "bar") + end + it 'does not duplicate other objects before serialization' do obj = UndupableObject.new diff --git a/spec/rspec/mocks/serialization_spec.rb b/spec/rspec/mocks/serialization_spec.rb index 530c68352..54ba93481 100644 --- a/spec/rspec/mocks/serialization_spec.rb +++ b/spec/rspec/mocks/serialization_spec.rb @@ -3,6 +3,7 @@ module RSpec module Mocks describe "Serialization of mocked objects" do + include_context 'with isolated configuration' class SerializableObject < Struct.new(:foo, :bar); end @@ -82,6 +83,7 @@ def set_stub end it 'marshals the same with and without stubbing' do + RSpec::Mocks.configuration.patch_marshal_to_support_partial_doubles = true expect { set_stub }.to_not change { Marshal.dump(serializable_object) } end end