Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Stash and restore aliased methods when the owner is reported wrong. #207

Merged
merged 1 commit into from

2 participants

@myronmarston

Fixes #206.

While I was at it, I wanted to verify that and_call_original works
with this case, so I added a spec for it, too.

@myronmarston myronmarston Stash and restore aliased methods when the owner is reported wrong.
Fixes #206.

While I was at it, I wanted to verify that `and_call_original` works
with this case, so I added a spec for it, too.
f86d02c
@alindeman alindeman merged commit ac90673 into master

1 check passed

Details default The Travis build passed
@myronmarston myronmarston deleted the handle_aliased_methods branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 20, 2012
  1. @myronmarston

    Stash and restore aliased methods when the owner is reported wrong.

    myronmarston authored
    Fixes #206.
    
    While I was at it, I wanted to verify that `and_call_original` works
    with this case, so I added a spec for it, too.
This page is out of date. Refresh to see the latest.
View
21 lib/rspec/mocks/instance_method_stasher.rb
@@ -30,14 +30,29 @@ def method_defined_directly_on_klass?
end
# @private
- def method_defined_on_klass?
- @klass.method_defined?(@method) || @klass.private_method_defined?(@method)
+ def method_defined_on_klass?(klass = @klass)
+ klass.method_defined?(@method) || klass.private_method_defined?(@method)
end
if ::UnboundMethod.method_defined?(:owner)
# @private
def method_owned_by_klass?
- @klass.instance_method(@method).owner == @klass
+ owner = @klass.instance_method(@method).owner
+ # On 1.8 (and some 1.9s -- e.g. rubinius) aliased methods
+ # can report the wrong owner. Example:
+ # class MyClass
+ # class << self
+ # alias alternate_new new
+ # end
+ # end
+ #
+ # MyClass.owner(:alternate_new) returns `Class` on 1.8,
+ # but we need to consider the owner to be `MyClass` because
+ # it is not actually available on `Class` but is on `MyClass`.
+ # Hence, we verify that the owner actually has the method defined.
+ # If the given owner does not have the method defined, we assume
+ # that the method is actually owned by @klass.
+ owner == @klass || !(method_defined_on_klass?(owner))
end
else
# @private
View
11 spec/rspec/mocks/and_call_original_spec.rb
@@ -96,6 +96,17 @@ def instance.foo; :bar; end
expect(inst.meth_1).to eq(:original)
end
+ it 'works for aliased methods' do
+ klass = Class.new do
+ class << self
+ alias alternate_new new
+ end
+ end
+
+ klass.should_receive(:alternate_new).and_call_original
+ expect(klass.alternate_new).to be_an_instance_of(klass)
+ end
+
context 'on an object that defines method_missing' do
before do
klass.class_eval do
View
27 spec/rspec/mocks/stash_spec.rb
@@ -11,6 +11,7 @@ def self.foo(arg)
end
end
end
+
it "keeps the original method intact after multiple expectations are added on the same method" do
klass.should_receive(:foo).with(:fizbaz).and_return(:wowwow)
klass.should_receive(:foo).with(:bazbar).and_return(:okay)
@@ -23,5 +24,31 @@ def self.foo(arg)
klass.foo(:yeah).should equal(:original_value)
end
end
+
+ describe "when a class method is aliased on a subclass and the method is mocked" do
+ let(:klass) do
+ Class.new do
+ class << self
+ alias alternate_new new
+ end
+ end
+ end
+
+ it "restores the original aliased public method" do
+ klass = Class.new do
+ class << self
+ alias alternate_new new
+ end
+ end
+
+ klass.should_receive(:alternate_new)
+ expect(klass.alternate_new).to be_nil
+
+ klass.rspec_verify
+
+ klass.rspec_reset
+ expect(klass.alternate_new).to be_an_instance_of(klass)
+ end
+ end
end
end
Something went wrong with that request. Please try again.