Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Commit 77b64fe

Browse files
committed
Resolves rspec/rspec-core#950 and adds specs
* Hopefully the code clarity is improved here * We also change the behavior by *not* duping an object if `space` is not yet initialized. This should have been the behavior from the beginning, but it was overlooked and did not have specs.
1 parent 65745a0 commit 77b64fe

File tree

2 files changed

+55
-7
lines changed

2 files changed

+55
-7
lines changed

lib/rspec/mocks/extensions/marshal.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
module Marshal
22
class << self
3-
def dump_with_mocks(*args)
4-
object = args.shift
5-
6-
if ( ::RSpec::Mocks.space && !::RSpec::Mocks.space.registered?(object) ) || NilClass === object
7-
return dump_without_mocks(*args.unshift(object))
3+
# Duplicates any mock objects before serialization. Otherwise,
4+
# serialization will fail because methods exist on the singleton class.
5+
def dump_with_mocks(object, *rest)
6+
if !::RSpec::Mocks.space || !::RSpec::Mocks.space.registered?(object) || NilClass === object
7+
dump_without_mocks(object, *rest)
8+
else
9+
dump_without_mocks(object.dup, *rest)
810
end
9-
10-
dump_without_mocks(*args.unshift(object.dup))
1111
end
1212

1313
alias_method :dump_without_mocks, :dump
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
require 'spec_helper'
2+
3+
describe Marshal, 'extensions' do
4+
# An object that raises when code attempts to dup it.
5+
#
6+
# Because we manipulate the internals of RSpec::Mocks.space below, we need
7+
# an object that simply blows up when #dup is called without using any
8+
# partial mocking or stubbing from rspec-mocks itself.
9+
class UndupableObject
10+
def dup
11+
raise NotImplementedError
12+
end
13+
end
14+
15+
describe '#dump' do
16+
context 'when rspec-mocks has not been fully initialized' do
17+
def without_space
18+
stashed_space, RSpec::Mocks.space = RSpec::Mocks.space, nil
19+
yield
20+
ensure
21+
RSpec::Mocks.space = stashed_space
22+
end
23+
24+
it 'does not duplicate the object before serialization' do
25+
obj = UndupableObject.new
26+
without_space do
27+
expect { Marshal.dump(obj) }.not_to raise_error
28+
end
29+
end
30+
end
31+
32+
context 'when rspec-mocks has been fully initialized' do
33+
it 'duplicates objects with stubbed or mocked implementations before serialization' do
34+
obj = double(:foo => "bar")
35+
expect { Marshal.dump(obj) }.not_to raise_error
36+
end
37+
38+
it 'does not duplicate other objects before serialization' do
39+
obj = UndupableObject.new
40+
expect { Marshal.dump(obj) }.not_to raise_error
41+
end
42+
43+
it 'does not duplicate nil before serialization' do
44+
expect { Marshal.dump(nil) }.not_to raise_error
45+
end
46+
end
47+
end
48+
end

0 commit comments

Comments
 (0)