Skip to content

Commit

Permalink
Handle additional any_instance / and_call_original edge cases.
Browse files Browse the repository at this point in the history
For #197.
  • Loading branch information
myronmarston committed Nov 25, 2012
1 parent d2ef056 commit 148db3c
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 8 deletions.
8 changes: 4 additions & 4 deletions lib/rspec/mocks/any_instance/recorder.rb
Expand Up @@ -113,6 +113,10 @@ def build_alias_method_name(method_name)
"__#{method_name}_without_any_instance__"
end

def already_observing?(method_name)
@observed_methods.include?(method_name)
end

private

def normalize_chain(*args)
Expand Down Expand Up @@ -165,10 +169,6 @@ def stop_observing!(method_name)
@observed_methods.delete(method_name)
end

def already_observing?(method_name)
@observed_methods.include?(method_name)
end

def observe!(method_name)
stop_observing!(method_name) if already_observing?(method_name)
@observed_methods << method_name
Expand Down
9 changes: 8 additions & 1 deletion lib/rspec/mocks/method_double.rb
Expand Up @@ -85,11 +85,18 @@ def original_method
end

def original_unrecorded_any_instance_method
return nil unless any_instance_class_recorder_observing_method?(@object.class)
alias_name = @object.class.__recorder.build_alias_method_name(@method_name)
return nil unless @object.respond_to?(alias_name)
@object.method(alias_name)
end

def any_instance_class_recorder_observing_method?(klass)
return true if klass.__recorder.already_observing?(@method_name)
superklass = klass.superclass
return false if superklass.nil?
any_instance_class_recorder_observing_method?(superklass)
end

if RUBY_VERSION.to_f > 1.8
# @private
def original_method_from_superclass
Expand Down
31 changes: 28 additions & 3 deletions spec/rspec/mocks/and_call_original_spec.rb
Expand Up @@ -37,9 +37,22 @@ def instance.foo; :bar; end
expect(instance.foo).to eq(:bar)
end

it 'works for an any_instance partial mock' do
klass.any_instance.should_receive(:meth_1).and_call_original
expect(klass.new.meth_1).to eq(:original)
context 'when using any_instance' do
it 'works for instance methods defined on the class' do
klass.any_instance.should_receive(:meth_1).and_call_original
expect(klass.new.meth_1).to eq(:original)
end

it 'works for instance methods defined on the superclass of the class' do
subclass = Class.new(klass)
subclass.any_instance.should_receive(:meth_1).and_call_original
expect(subclass.new.meth_1).to eq(:original)
end

it 'works when mocking the method on one class and calling the method on an instance of a subclass' do
klass.any_instance.should_receive(:meth_1).and_call_original
expect(Class.new(klass).new.meth_1).to eq(:original)
end
end

if RUBY_VERSION.to_f > 1.8
Expand Down Expand Up @@ -103,6 +116,18 @@ def method_missing(name, *args)
expect(instance.greet_jack).to eq("Hello, jack")
end

it 'works for an any_instance partial mock' do
klass.any_instance.should_receive(:greet_jack).and_call_original
expect(instance.greet_jack).to eq("Hello, jack")
end

it 'raises an error for an unhandled message for an any_instance partial mock' do
klass.any_instance.should_receive(:not_a_handled_message).and_call_original
expect {
instance.not_a_handled_message
}.to raise_error(NameError, /not_a_handled_message/)
end

it 'raises an error on invocation if method_missing does not handle the message' do
instance.should_receive(:not_a_handled_message).and_call_original

Expand Down

0 comments on commit 148db3c

Please sign in to comment.