Skip to content

Commit

Permalink
Test and fix for call_through w/ instance methods
Browse files Browse the repository at this point in the history
  • Loading branch information
lreeves committed Aug 11, 2016
1 parent 753e3ab commit 651ec6b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 9 deletions.
44 changes: 35 additions & 9 deletions lib/spy/subroutine.rb
Expand Up @@ -135,13 +135,29 @@ def and_yield(*args)
# tells the spy to call the original method
# @return [self]
def and_call_through
@plan = Proc.new do |*args, &block|
if original_method
original_method.call(*args, &block)
else
base_object.send(:method_missing, method_name, *args, &block)
if @base_object.is_a? Class
@plan = Proc.new do |object, *args, &block|
if original_method
if original_method.is_a? UnboundMethod
bound_method = original_method.bind(object)
bound_method.call(*args, &block)
else
original_method.call(*args, &block)
end
else
base_object.send(:method_missing, method_name, *args, &block)
end
end
else
@plan = Proc.new do |*args, &block|
if original_method
original_method.call(*args, &block)
else
base_object.send(:method_missing, method_name, *args, &block)
end
end
end

self
end

Expand Down Expand Up @@ -202,10 +218,18 @@ def has_been_called_with?(*args)
# method.
def invoke(object, args, block, called_from)
check_arity!(args.size)
result = if @plan
check_for_too_many_arguments!(@plan)
@plan.call(*args, &block)
end

if base_object.is_a? Class
result = if @plan
check_for_too_many_arguments!(@plan)
@plan.call(object, *args, &block)
end
else
result = if @plan
check_for_too_many_arguments!(@plan)
@plan.call(*args, &block)
end
end
ensure
calls << CallLog.new(object, called_from, args, block, result)
end
Expand Down Expand Up @@ -273,6 +297,8 @@ def check_for_too_many_arguments!(block)
min_arity = block.arity
min_arity = min_arity.abs - 1 if min_arity < 0

min_arity -=1 if base_object.is_a? Class # Instance-method procs take an extra param for receiving object

if min_arity > arity_range.max
raise ArgumentError.new("block requires #{min_arity} arguments while original_method require a maximum of #{arity_range.max}")
end
Expand Down
6 changes: 6 additions & 0 deletions test/integration/test_instance_method.rb
Expand Up @@ -17,6 +17,12 @@ def teardown
Spy::Agency.instance.dissolve!
end

def test_call_through_with_instance_method
Spy.on_instance_method(Foo, :bar).and_call_through
assert_equal "foobar", Foo.new.bar
Spy.off_instance_method(Foo, :bar)
end

def test_it_overides_all_methods
assert_equal Foo.new.bar, "foobar"
spy = Spy.on_instance_method(Foo, bar: "timshel")
Expand Down

0 comments on commit 651ec6b

Please sign in to comment.