Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle keyword arguments separately for and_call_original in supported rubies #1324

Closed
wants to merge 11 commits into from
21 changes: 20 additions & 1 deletion lib/rspec/mocks/message_expectation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def and_return(first_value, *values)
# expect(counter.count).to eq(original_count + 1)
def and_call_original
wrap_original(__method__) do |original, *args, &block|
original.call(*args, &block)
__call_original(original, *args, &block)
end
end

Expand Down Expand Up @@ -354,6 +354,25 @@ def to_s
end
alias inspect to_s

private

if RSpec::Support::RubyFeatures.kw_args_supported?
def __call_original(original, *args, &block)
if RSpec::Support::MethodSignature.new(original).has_kw_args_in?(args)
binding.eval(<<-CODE, __FILE__, __LINE__)
benoittgt marked this conversation as resolved.
Show resolved Hide resolved
kwargs = args.pop
original.call(*args, **kwargs, &block)
CODE
else
original.call(*args, &block)
end
end
else
def __call_original(original, *args, &block)
original.call(*args, &block)
end
end

# @private
# Contains the parts of `MessageExpectation` that aren't part of
# rspec-mocks' public API. The class is very big and could really use
Expand Down
17 changes: 17 additions & 0 deletions spec/rspec/mocks/and_call_original_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ def meth_2(x)
yield x, :additional_yielded_arg
end

if RSpec::Support::RubyFeatures.kw_args_supported?
binding.eval(<<-CODE, __FILE__, __LINE__)
def meth_3(keyword_arg: nil)
keyword_arg
end
CODE
end

def self.new_instance
new
end
Expand Down Expand Up @@ -59,6 +67,15 @@ def self.new_instance
expect(value).to eq([:submitted_arg, :additional_yielded_arg])
end

if RSpec::Support::RubyFeatures.kw_args_supported?
it 'works with keyword arguments' do
expect(instance).to receive(:meth_3).and_call_original
binding.eval(<<-CODE, __FILE__, __LINE__)
expect(instance.meth_3(keyword_arg: :original_arg)).to eq :original_arg
CODE
end
end

it 'errors when you pass through the wrong number of args' do
expect(instance).to receive(:meth_1).and_call_original
expect(instance).to receive(:meth_2).twice.and_call_original
Expand Down