Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Externalize methods and state that was previously held on all objects.

- Remove `@mock_proxy` ivar
- Remove `rspec_verify`, `rspec_reset`, `__mock_proxy` and `__remove_mock_proxy` methods.

This is a refactoring that I'm doing to pave the way for the new expect
syntax (#153). As that syntax "wraps" objects in order to mock or stub
them, we need to externalize these methods and state. The methods directly
on the object (e.g. `stub` and `should_receive`) will simply delegate to
this external logic.

This refactoring had some nice side benefits:

- No need for the hacky YAML fix. It was only needed because we were storing
  `@mock_proxy` on the mocked object.
- AnyInstance no longer needs to much with `dup`; again, this was only needed
  because it dup'd the `@mock_proxy` ivar.
- The Marshal extension gets significantly simpler (again, due to not
  storing `@mock_proxy` on the object anymore).

Rather than storing the mock proxies on the objects, we are now storing
them in a hash, keyed by object_id.  This is pretty simple and consistent,
but could be problematic for objects that muck with `object_id`. That method
seems a bit sacred, though, so I'm not too worried about it.
  • Loading branch information...
commit 210c9f02872b2afcea67c6fcb992a13535cb94d7 1 parent 73fb798
@myronmarston myronmarston authored
View
42 lib/rspec/mocks/any_instance.rb
@@ -26,57 +26,37 @@ module AnyInstance
#
# @return [Recorder]
def any_instance
- RSpec::Mocks::space.add(self)
- modify_dup_to_remove_mock_proxy_when_invoked
+ AnyInstance.tracked_klasses << self
__recorder
end
# @private
def rspec_verify
__recorder.verify
- super
ensure
__recorder.stop_all_observation!
- restore_dup
@__recorder = nil
end
# @private
- def rspec_reset
- restore_dup
- __mock_proxy.reset
- end
-
- # @private
def __recorder
@__recorder ||= AnyInstance::Recorder.new(self)
end
- private
- def modify_dup_to_remove_mock_proxy_when_invoked
- if method_defined?(:dup) and !method_defined?(:__rspec_original_dup)
- class_eval do
- def __rspec_dup(*arguments, &block)
- clone = __rspec_original_dup(*arguments, &block)
- clone.send :__remove_mock_proxy
- clone
- end
-
- alias_method :__rspec_original_dup, :dup
- alias_method :dup, :__rspec_dup
- end
+ def self.verify_all
+ tracked_klasses.each do |klass|
+ klass.rspec_verify
end
end
- def restore_dup
- if method_defined?(:__rspec_original_dup)
- class_eval do
- alias_method :dup, :__rspec_original_dup
- remove_method :__rspec_original_dup
- remove_method :__rspec_dup
- end
- end
+ def self.reset_all
+ tracked_klasses.clear
+ end
+
+ def self.tracked_klasses
+ @tracked_klasses ||= []
end
end
end
end
+
View
2  lib/rspec/mocks/any_instance/recorder.rb
@@ -103,7 +103,7 @@ def stop_all_observation!
# @private
def playback!(instance, method_name)
- RSpec::Mocks::space.add(instance)
+ RSpec::Mocks.space.ensure_registered(instance)
message_chains.playback!(instance, method_name)
@played_methods[method_name] = instance
received_expected_message!(method_name) if message_chains.has_expectation?(method_name)
View
14 lib/rspec/mocks/extensions/marshal.rb
@@ -2,18 +2,12 @@ module Marshal
class << self
def dump_with_mocks(*args)
object = args.shift
- return dump_without_mocks(*args.unshift(object)) unless object.instance_variable_defined?(:@mock_proxy)
- mp = object.instance_variable_get(:@mock_proxy)
- return dump_without_mocks(*args.unshift(object)) unless mp.is_a?(::RSpec::Mocks::Proxy)
-
- object.__send__(:remove_instance_variable, :@mock_proxy)
-
- begin
- dump_without_mocks(*args.unshift(object.dup))
- ensure
- object.instance_variable_set(:@mock_proxy,mp)
+ unless ::RSpec::Mocks.space.registered?(object)
+ return dump_without_mocks(*args.unshift(object))
end
+
+ dump_without_mocks(*args.unshift(object.dup))
end
alias_method :dump_without_mocks, :dump
View
23 lib/rspec/mocks/extensions/psych.rb
@@ -1,23 +0,0 @@
-if defined?(Psych) && Psych.respond_to?(:dump)
- module Psych
- class << self
- def dump_with_mocks(object, *args)
- return dump_without_mocks(object, *args) unless object.instance_variable_defined?(:@mock_proxy)
-
- mp = object.instance_variable_get(:@mock_proxy)
- return dump_without_mocks(object, *args) unless mp.is_a?(::RSpec::Mocks::Proxy)
-
- object.__send__(:remove_instance_variable, :@mock_proxy)
-
- begin
- dump_without_mocks(object, *args)
- ensure
- object.instance_variable_set(:@mock_proxy, mp)
- end
- end
-
- alias_method :dump_without_mocks, :dump
- alias_method :dump, :dump_with_mocks
- end
- end
-end
View
2  lib/rspec/mocks/framework.rb
@@ -17,7 +17,7 @@
require 'rspec/mocks/errors'
require 'rspec/mocks/error_generator'
require 'rspec/mocks/space'
-require 'rspec/mocks/serialization'
+require 'rspec/mocks/extensions/marshal'
require 'rspec/mocks/any_instance'
require 'rspec/mocks/mutate_const'
require 'rspec/mocks/stub_chain'
View
3  lib/rspec/mocks/method_double.rb
@@ -142,7 +142,6 @@ class << @object; self; end
# @private
def configure_method
- RSpec::Mocks::space.add(@object) if RSpec::Mocks::space
warn_if_nil_class
@original_visibility = visibility_for_method
@method_stasher.stash unless @method_is_proxied
@@ -155,7 +154,7 @@ def define_proxy_method
object_singleton_class.class_eval <<-EOF, __FILE__, __LINE__ + 1
def #{@method_name}(*args, &block)
- __mock_proxy.message_received :#{@method_name}, *args, &block
+ ::RSpec::Mocks.space.mock_proxy_for(self).message_received :#{@method_name}, *args, &block
end
#{visibility_for_method}
EOF
View
44 lib/rspec/mocks/methods.rb
@@ -12,13 +12,15 @@ module Methods
# logger.should_receive(:log)
# thing_that_logs.do_something_that_logs_a_message
def should_receive(message, opts={}, &block)
- __mock_proxy.add_message_expectation(opts[:expected_from] || caller(1)[0], message.to_sym, opts, &block)
+ mock_proxy = ::RSpec::Mocks.space.mock_proxy_for(self)
+ mock_proxy.add_message_expectation(opts[:expected_from] || caller(1)[0], message.to_sym, opts, &block)
end
# Sets and expectation that this object should _not_ receive a message
# during this example.
def should_not_receive(message, &block)
- __mock_proxy.add_negative_message_expectation(caller(1)[0], message.to_sym, &block)
+ mock_proxy = ::RSpec::Mocks.space.mock_proxy_for(self)
+ mock_proxy.add_negative_message_expectation(caller(1)[0], message.to_sym, &block)
end
# Tells the object to respond to the message with the specified value.
@@ -32,7 +34,7 @@ def stub(message_or_hash, opts={}, &block)
if Hash === message_or_hash
message_or_hash.each {|message, value| stub(message).and_return value }
else
- __mock_proxy.add_stub(caller(1)[0], message_or_hash.to_sym, opts, &block)
+ ::RSpec::Mocks.space.mock_proxy_for(self).add_stub(caller(1)[0], message_or_hash.to_sym, opts, &block)
end
end
@@ -44,7 +46,7 @@ def stub(message_or_hash, opts={}, &block)
# shared `before` hook for the common case, but you want to replace it
# for a special case.
def unstub(message)
- __mock_proxy.remove_stub(message)
+ ::RSpec::Mocks.space.mock_proxy_for(self).remove_stub(message)
end
def stub!(message_or_hash, opts={}, &block)
@@ -93,7 +95,7 @@ def stub_chain(*chain, &blk)
# returned.
def as_null_object
@_null_object = true
- __mock_proxy.as_null_object
+ ::RSpec::Mocks.space.mock_proxy_for(self).as_null_object
end
# Returns true if this object has received `as_null_object`
@@ -103,37 +105,9 @@ def null_object?
# @private
def received_message?(message, *args, &block)
- __mock_proxy.received_message?(message, *args, &block)
- end
-
- # @private
- def rspec_verify
- __mock_proxy.verify
- end
-
- # @private
- def rspec_reset
- __mock_proxy.reset
- end
-
- private
-
- def __mock_proxy
- @mock_proxy ||= begin
- mp = if TestDouble === self
- Proxy.new(self, @name, @options)
- else
- Proxy.new(self)
- end
-
- Serialization.fix_for(self)
- mp
- end
- end
-
- def __remove_mock_proxy
- @mock_proxy = nil
+ ::RSpec::Mocks.space.mock_proxy_for(self).received_message?(message, *args, &block)
end
end
end
end
+
View
18 lib/rspec/mocks/mutate_const.rb
@@ -345,27 +345,13 @@ def rspec_reset
def self.mutate(mutator)
register_mutator(mutator)
mutator.mutate
- ensure_registered_with_mocks_space
- end
-
- # Ensures the constant stubbing is registered with
- # rspec-mocks space so that stubbed constants can
- # be restored when examples finish.
- #
- # @api private
- def self.ensure_registered_with_mocks_space
- return if defined?(@registered_with_mocks_space) && @registered_with_mocks_space
- ::RSpec::Mocks.space.add(self)
- @registered_with_mocks_space = true
end
# Resets all stubbed constants. This is called automatically
# by rspec-mocks when an example finishes.
#
# @api private
- def self.rspec_reset
- @registered_with_mocks_space = false
-
+ def self.reset_all
# We use reverse order so that if the same constant
# was stubbed multiple times, the original value gets
# properly restored.
@@ -411,4 +397,4 @@ def self.raise_on_invalid_const
# of both stubbing and hiding.
ConstantStubber = ConstantMutator
end
-end
+end
View
4 lib/rspec/mocks/proxy.rb
@@ -17,9 +17,9 @@ def warn_about_expectations_on_nil=(new_value)
def allow_message_expectations_on_nil
@warn_about_expectations_on_nil = false
- # ensure nil.rspec_verify is called even if an expectation is not set in the example
+ # ensure nil is verified even if an expectation is not set in the example
# otherwise the allowance would effect subsequent examples
- RSpec::Mocks::space.add(nil) unless RSpec::Mocks::space.nil?
+ RSpec::Mocks.space.ensure_registered(nil) unless RSpec::Mocks.space.nil?
end
# @private
View
34 lib/rspec/mocks/serialization.rb
@@ -1,34 +0,0 @@
-require 'rspec/mocks/extensions/marshal'
-require 'rspec/mocks/extensions/psych' if defined?(::Psych)
-
-module RSpec
- module Mocks
- # @private
- module Serialization
- # @private
- def self.fix_for(object)
- object.extend(YAML) if defined?(::YAML)
- rescue TypeError
- # Can't extend Fixnums, Symbols, true, false, or nil
- end
-
- # @private
- module YAML
- # @private
- def to_yaml(options = {})
- return nil if defined?(::Psych) && options.respond_to?(:[]) && options[:nodump]
- return super(options) unless instance_variable_defined?(:@mock_proxy)
-
- mp = @mock_proxy
- remove_instance_variable(:@mock_proxy)
-
- begin
- super(options)
- ensure
- @mock_proxy = mp
- end
- end
- end
- end
- end
-end
View
38 lib/rspec/mocks/space.rb
@@ -2,21 +2,29 @@ module RSpec
module Mocks
# @api private
class Space
- def add(obj)
- receivers << obj unless receivers.detect {|m| m.equal? obj}
+ attr_reader :mock_proxies
+
+ def initialize
+ @mock_proxies = {}
end
def verify_all
- receivers.each do |mock|
- mock.rspec_verify
+ mock_proxies.values.each do |object|
+ object.verify
end
+
+ AnyInstance.verify_all
end
def reset_all
- receivers.each do |mock|
- mock.rspec_reset
+ ConstantMutator.reset_all
+ AnyInstance.reset_all
+
+ mock_proxies.values.each do |object|
+ object.reset
end
- receivers.clear
+
+ mock_proxies.clear
expectation_ordering.clear
end
@@ -24,10 +32,20 @@ def expectation_ordering
@expectation_ordering ||= OrderGroup.new
end
- private
+ def mock_proxy_for(object)
+ mock_proxies.fetch(object.object_id) do
+ mock_proxies[object.object_id] = if TestDouble === object
+ object.__build_mock_proxy
+ else
+ Proxy.new(object)
+ end
+ end
+ end
+
+ alias ensure_registered mock_proxy_for
- def receivers
- @receivers ||= []
+ def registered?(object)
+ mock_proxies.has_key?(object.object_id)
end
end
end
View
4 lib/rspec/mocks/stub_chain.rb
@@ -42,8 +42,8 @@ def format_chain(*chain, &blk)
end
def find_matching_stub
- object.__send__(:__mock_proxy).
- __send__(:find_matching_method_stub, chain.first.to_sym)
+ ::RSpec::Mocks.space.mock_proxy_for(object).
+ __send__(:find_matching_method_stub, chain.first.to_sym)
end
end
end
View
11 lib/rspec/mocks/test_double.rb
@@ -50,6 +50,11 @@ def respond_to?(message, incl_private=false)
__mock_proxy.null_object? && message != :to_ary ? true : super
end
+ # @private
+ def __build_mock_proxy
+ Proxy.new(self, @name, @options)
+ end
+
private
def __initialize_as_test_double(name=nil, stubs_and_options={})
@@ -98,6 +103,12 @@ def assign_stubs(stubs)
stub(message).and_return(response)
end
end
+
+ private
+
+ def __mock_proxy
+ ::RSpec::Mocks.space.mock_proxy_for(self)
+ end
end
end
end
View
34 spec/rspec/mocks/any_instance_spec.rb
@@ -324,7 +324,7 @@ class RSpec::SampleRspecTestClass;end
klass.any_instance.should_receive(:foo)
klass.any_instance.should_not_receive(:bar)
klass.new.foo
- verify klass
+ RSpec::Mocks.space.verify_all
end
end
end
@@ -343,14 +343,14 @@ class RSpec::SampleRspecTestClass;end
expect do
klass.any_instance.should_receive(:foo)
klass.new
- verify klass
+ RSpec::Mocks.space.verify_all
end.to raise_error(RSpec::Mocks::MockExpectationError, foo_expectation_error_message)
end
it "fails if no instance is created" do
expect do
klass.any_instance.should_receive(:foo).and_return(1)
- verify klass
+ RSpec::Mocks.space.verify_all
end.to raise_error(RSpec::Mocks::MockExpectationError, foo_expectation_error_message)
end
@@ -358,7 +358,7 @@ class RSpec::SampleRspecTestClass;end
expect do
klass.any_instance.should_receive(:foo)
klass.any_instance.should_receive(:bar)
- verify klass
+ RSpec::Mocks.space.verify_all
end.to raise_error(RSpec::Mocks::MockExpectationError, 'Exactly one instance should have received the following message(s) but didn\'t: bar, foo')
end
@@ -396,7 +396,7 @@ class RSpec::SampleRspecTestClass;end
klass.any_instance.should_receive(:foo)
klass.should_receive(:woot)
klass.new.foo
- verify klass
+ RSpec::Mocks.space.verify_all
end.to(raise_error(RSpec::Mocks::MockExpectationError) do |error|
expect(error.message).not_to eq(existing_method_expectation_error_message)
end)
@@ -422,14 +422,14 @@ class RSpec::SampleRspecTestClass;end
expect do
klass.any_instance.should_receive(:existing_method)
klass.new
- verify klass
+ RSpec::Mocks.space.verify_all
end.to raise_error(RSpec::Mocks::MockExpectationError, existing_method_expectation_error_message)
end
it "fails if no instance is created" do
expect do
klass.any_instance.should_receive(:existing_method)
- verify klass
+ RSpec::Mocks.space.verify_all
end.to raise_error(RSpec::Mocks::MockExpectationError, existing_method_expectation_error_message)
end
@@ -437,7 +437,7 @@ class RSpec::SampleRspecTestClass;end
expect do
klass.any_instance.should_receive(:existing_method)
klass.any_instance.should_receive(:another_existing_method)
- verify klass
+ RSpec::Mocks.space.verify_all
end.to raise_error(RSpec::Mocks::MockExpectationError, 'Exactly one instance should have received the following message(s) but didn\'t: another_existing_method, existing_method')
end
@@ -531,7 +531,7 @@ def foo; end
it "fails when no instances are declared" do
expect do
klass.any_instance.should_receive(:foo).once
- verify klass
+ RSpec::Mocks.space.verify_all
end.to raise_error(RSpec::Mocks::MockExpectationError, foo_expectation_error_message)
end
@@ -539,7 +539,7 @@ def foo; end
expect do
klass.any_instance.should_receive(:foo).once
klass.new
- verify klass
+ RSpec::Mocks.space.verify_all
end.to raise_error(RSpec::Mocks::MockExpectationError, foo_expectation_error_message)
end
@@ -645,7 +645,7 @@ def foo; end
context "the 'never' constraint" do
it "passes for 0 invocations" do
klass.any_instance.should_receive(:foo).never
- verify klass
+ RSpec::Mocks.space.verify_all
end
it "fails on the first invocation" do
@@ -666,7 +666,7 @@ def foo; end
expect do
klass.any_instance.should_receive(:foo).never
klass.any_instance.should_receive(:existing_method).and_return(5)
- verify klass
+ RSpec::Mocks.space.verify_all
end.to raise_error(RSpec::Mocks::MockExpectationError, existing_method_expectation_error_message)
end
end
@@ -702,7 +702,7 @@ def foo; end
expect do
klass.any_instance.should_receive(:foo).any_number_of_times
klass.any_instance.should_receive(:existing_method).and_return(5)
- verify klass
+ RSpec::Mocks.space.verify_all
end.to raise_error(RSpec::Mocks::MockExpectationError, existing_method_expectation_error_message)
end
end
@@ -715,7 +715,7 @@ def foo; end
context "existing method" do
before(:each) do
- space.add(klass)
+ klass.any_instance # to force it to be tracked
end
context "with stubbing" do
@@ -836,7 +836,7 @@ def foo; end
klass.any_instance.stub(:existing_method).and_return(false)
klass.any_instance.stub(:existing_method).and_return(true)
- verify klass
+ RSpec::Mocks.space.verify_all
expect(klass.new).to respond_to(:existing_method)
expect(klass.new.existing_method).to eq(existing_method_return_value)
end
@@ -844,14 +844,14 @@ def foo; end
it "adds an class to the current space when #any_instance is invoked" do
klass.any_instance
- expect(RSpec::Mocks::space.send(:receivers)).to include(klass)
+ expect(AnyInstance.tracked_klasses).to include(klass)
end
it "adds an instance to the current space when stubbed method is invoked" do
klass.any_instance.stub(:foo)
instance = klass.new
instance.foo
- expect(RSpec::Mocks::space.send(:receivers)).to include(instance)
+ expect(RSpec::Mocks.space.mock_proxies.keys).to include(instance.object_id)
end
end
View
8 spec/rspec/mocks/methods_spec.rb
@@ -14,11 +14,9 @@ def methods_added_to_all_objects
# If really necessary, you can add to this list, but long term,
# we are hoping to cut down on the number of methods added to all objects
expect(methods_added_to_all_objects).to match_array([
- :__mock_proxy, :__remove_mock_proxy, :as_null_object,
- :null_object?, :received_message?,
- :rspec_reset, :rspec_verify, :should_not_receive,
- :should_receive, :stub, :stub!,
- :stub_chain, :unstub, :unstub!
+ :as_null_object, :null_object?,
+ :received_message?, :should_not_receive, :should_receive,
+ :stub, :stub!, :stub_chain, :unstub, :unstub!
])
end
end
View
79 spec/rspec/mocks/mock_space_spec.rb
@@ -4,58 +4,61 @@
module RSpec
module Mocks
describe Space do
- before :each do
- @space = RSpec::Mocks::Space.new
- klazz = Class.new do
- def rspec_verify
- @verified = true
- end
- def verified?
- @verified
- end
- def rspec_reset
- @reset = true
- end
- def reset?
- @reset
- end
- end
- @m1 = klazz.new
- @m2 = klazz.new
+ let(:space) { RSpec::Mocks::Space.new }
+ let(:dbl_1) { Object.new }
+ let(:dbl_2) { Object.new }
+
+ before do
+ space.ensure_registered(dbl_1)
+ space.ensure_registered(dbl_2)
end
it "verifies all mocks within" do
- @space.add(@m1)
- @space.add(@m2)
- @space.verify_all
- expect(@m1).to be_verified
- expect(@m2).to be_verified
+ verifies = []
+
+ space.mock_proxy_for(dbl_1).stub(:verify) { verifies << :dbl_1 }
+ space.mock_proxy_for(dbl_2).stub(:verify) { verifies << :dbl_2 }
+
+ space.verify_all
+
+ expect(verifies).to eq([:dbl_1, :dbl_2])
end
it "resets all mocks within" do
- @space.add(m1 = double("mock1"))
- @space.add(m2 = double("mock2"))
- m1.should_receive(:rspec_reset)
- m2.should_receive(:rspec_reset)
- @space.reset_all
+ resets = []
+
+ space.mock_proxy_for(dbl_1).stub(:reset) { resets << :dbl_1 }
+ space.mock_proxy_for(dbl_2).stub(:reset) { resets << :dbl_2 }
+
+ space.reset_all
+
+ expect(resets).to eq([:dbl_1, :dbl_2])
end
- it "clears internal mocks on reset_all" do
- @space.add(double("mock"))
- @space.reset_all
- expect(@space.instance_eval { receivers.empty? }).to be_true
+ it "does not leak mock proxies between examples" do
+ expect {
+ space.reset_all
+ }.to change { space.mock_proxies.size }.to(0)
end
it "resets the ordering" do
- @space.reset_all
- expect(@space.expectation_ordering).to be_empty
+ space.expectation_ordering.register :some_expectation
+
+ expect {
+ space.reset_all
+ }.to change { space.expectation_ordering.empty? }.from(false).to(true)
end
it "only adds an instance once" do
- @space.add(m1 = double("mock1"))
- @space.add(m1)
- m1.should_receive(:rspec_verify)
- @space.verify_all
+ m1 = double("mock1")
+
+ expect {
+ space.ensure_registered(m1)
+ }.to change { space.mock_proxies }
+
+ expect {
+ space.ensure_registered(m1)
+ }.not_to change { space.mock_proxies }
end
end
end
View
23 spec/rspec/mocks/serialization_spec.rb
@@ -2,22 +2,10 @@
module RSpec
module Mocks
- describe Serialization do
+ describe "Serialization of mocked objects" do
class SerializableObject < Struct.new(:foo, :bar); end
- class SerializableMockProxy
- attr_reader :mock_proxy
-
- def initialize(mock_proxy)
- @mock_proxy = mock_proxy
- end
-
- def ==(other)
- other.class == self.class && other.mock_proxy == mock_proxy
- end
- end
-
def self.with_yaml_loaded(&block)
context 'with YAML loaded' do
module_eval(&block)
@@ -96,15 +84,6 @@ def set_stub
it 'marshals the same with and without stubbing' do
expect { set_stub }.to_not change { Marshal.dump(serializable_object) }
end
-
- describe "an object that has its own mock_proxy instance variable" do
- let(:serializable_object) { RSpec::Mocks::SerializableMockProxy.new(:my_mock_proxy) }
-
- it 'does not interfere with its marshalling' do
- marshalled_copy = Marshal.load(Marshal.dump(serializable_object))
- expect(marshalled_copy).to eq serializable_object
- end
- end
end
end
end
View
4 spec/spec_helper.rb
@@ -12,11 +12,11 @@
module VerifyAndResetHelpers
def verify(object)
- object.rspec_verify
+ RSpec::Mocks.space.mock_proxy_for(object).verify
end
def reset(object)
- object.rspec_reset
+ RSpec::Mocks.space.mock_proxy_for(object).reset
end
end

7 comments on commit 210c9f0

@alindeman
Collaborator

Flyby review: could we use __id__ instead? Would that address your concern about objects that muck with object_id?

@myronmarston

Flyby review: could we use id instead? Would that address your concern about objects that muck with object_id?

I didn't even know about __id__! Not sure how I missed that...

Anyhow, I was playing around in IRB and noticed that BasicObject provides __id__ but not object_id:

➜  ~  irb
1.9.3p327 :001 > k = BasicObject.new
(Object doesn't support #inspect)
 =>
1.9.3p327 :002 > k.__id__
 => 70139647345580
1.9.3p327 :003 > k.object_id
NoMethodError: undefined method `object_id' for #<BasicObject:0x007f9551878758>
    from (irb):3
    from /Users/myron/.rvm/rubies/ruby-1.9.3-p327/bin/irb:16:in `<main>'
1.9.3p327 :004 >

So it looks like we should use __id__. I checked in IRB on 1.8.6 and noticed that method works there, as well. There's still the possibility of someone mucking with __id__ but I feel like the underscores communicate "this is off limits; don't mess with this" and an object that redefines __id__ is a poorly behaved object, IMO.

@alindeman
Collaborator

Awesome! Exactly, what I meant (but didn't exactly say) is that I consider any object that messes with __ methods to be completely insane and unsupported.

I forgot that __id__ was on BasicObject too. Good find.

@myronmarston

I just pushed a PR (#259) for this :). Will merge when travis is green. (But feel free to review it if you want).

@dchelimsky
Owner

@myronmarston can we eliminate the serialization_spec entirely after this commit? Asking because I'd like to get rid of the warning Ruby 2.0 emits saying "syck has been removed" triggered by https://github.com/rspec/rspec-mocks/blob/master/spec/rspec/mocks/serialization_spec.rb#L63

@myronmarston

@myronmarston can we eliminate the serialization_spec entirely after this commit? Asking because I'd like to get rid of the warning Ruby 2.0 emits saying "syck has been removed" triggered by https://github.com/rspec/rspec-mocks/blob/master/spec/rspec/mocks/serialization_spec.rb#L63

I don't think we can remove it entirely. We still have our marshal fix that it is testing. We don't have any YAML-specific code in rspec-mocks, anymore, but given that it was a bug in the past I'd like to keep the YAML specs to prevent future regressions.

What do you think about putting ruby version conditionals in place so that on 2.0 the syck one is skipped?

@dchelimsky
Owner

I had done that locally and felt bad about it :) But if you think that's fine I'll make it so.

Please sign in to comment.
Something went wrong with that request. Please try again.