Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Issue with kwargs in and_invoke #1594

Closed
@kinkou

Description

@kinkou

Subject of the issue

When lambdas passed to and_invoke are called with keyword arguments, rspec-mocks fails with ArgumentError: wrong number of arguments.

Changing RSpec::Mocks::AndInvokeImplementation#call to…

def call(*args, **kwargs, &block)
  proc = if @procs_to_invoke.size > 1
           @procs_to_invoke.shift
         else
           @procs_to_invoke.first
         end

  proc.call(*args, **kwargs, &block)
end

…seems to fix the issue.

Your environment

  • Ruby version: 3.3.4
  • rspec-mocks version: 3.13.1

Steps to reproduce

# ./and_invoke.rb
class AndInvoke
  def call(positional_arg, keyword_arg:)
    puts "Original method called"
  end
end

# ./spec/and_invoke_spec.rb
require_relative 'spec_helper'
require_relative '../and_invoke'

describe AndInvoke do
  let(:instance) { described_class.new }

  before do
    allow(instance).to(
      receive(:call)
        .and_invoke(
          ->(positional_arg, keyword_arg:) { puts "Replacing lambda called" }
        )
    )
  end

  it 'invokes lambda instead of the original method' do
    instance.call('positional_arg', keyword_arg: 'keyword_arg')

    expect(instance).to(
      have_received(:call)
        .with('positional_arg', keyword_arg: 'keyword_arg')
    )
  end
end

Expected behavior

$ bundle exec rspec spec/and_invoke_spec.rb 
Replacing lambda called
.

Finished in 0.00377 seconds (files took 0.04207 seconds to load)
1 example, 0 failures

Actual behavior

$ bundle exec rspec spec/and_invoke_spec.rb 
F

Failures:

  1) AndInvoke invokes lambda instead of the original method
     Failure/Error: ->(positional_arg, keyword_arg:) { puts "Replacing lambda called" }
     
     ArgumentError:
       wrong number of arguments (given 2, expected 1; required keyword: keyword_arg)
     # ./spec/and_invoke_spec.rb:10:in `block (3 levels) in <top (required)>'
     # ./spec/and_invoke_spec.rb:15:in `block (2 levels) in <top (required)>'

Finished in 0.00358 seconds (files took 0.04281 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/and_invoke_spec.rb:14 # AndInvoke invokes lambda instead of the original method

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions