freerange/mocha — pull request #175 by floehopper (2013-12-30 16:01:42+00:00)
Title: Consider stubs on superclass receivers if none exist on primary receiver.

Note: This may break existing tests which rely on the old behaviour!

Stubbing a superclass method and then invoking that method on a child
class would previously cause an unexpected invocation error. This was
because the superclass and child class delegated to different mock
objects i.e. the superclass has its own `@mocha` class instance variable
which is different from the child class' `@mocha` class instance
variable.

By searching up through the inheritance hierarchy for each of the delegate
mock objects, we can provide more intuitive behaviour. Instead of
an unexpected invocation error (see above), invoking the method on the
child class will cause the stubbed method on the superclass to be used.

class Parent
def self.my_class_method
:original_value
end
end

class Child < Parent
end

Parent.stubs(:my_class_method).returns(:stubbed_value)

# old behaviour
Child.my_class_method # => unexpected invocation error

# new behaviour
Child.my_class_method # => :stubbed_value

For consistency, I have also implemented a similar change for the
corresponding `any_instance` scenario:

class Parent
def my_instance_method
:original_value
end
end

class Child < Parent
end

Parent.any_instance.stubs(:my_instance_method).returns(:stubbed_value)

# old behaviour
Child.new.my_instance_method # => unexpected invocation error

# new behaviour
Child.new.my_instance_method # => :stubbed_value

These changes were largely based on changes suggested by @ccutrer in #145.