rspec-mocks icon indicating copy to clipboard operation
rspec-mocks copied to clipboard

Using the last argument as keyword parameters is deprecated for arbitrary handling with a block

Open linkyndy opened this issue 4 years ago • 7 comments

Subject of the issue

I am performing a complex expectation as described in the arbitrary handling section of the docs. Here is the expectation:

expect(double).to receive(:method) do |item:, &block|
  expect(item).to eq(item)
  expect(another_double).to receive(:another_method)
  # ...other expectations...
  block.call(another_double)
end

I get the following warning from Ruby 2.7:

/Users/foo/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/rspec-mocks-3.9.1/lib/rspec/mocks/message_expectation.rb:694: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/Users/foo/project/spec/bar_spec.rb:33: warning: The called method `call' is defined here

where the line mentioned is the first line in the Ruby snippet above.

Your environment

  • Ruby version: 2.7.0
  • rspec-mocks version: 3.9.1

I am not sure how I can fix this; tried expect(double).to receive(:method) do |item:, **kwargs, &block| but it yielded the same error.

linkyndy avatar Apr 13 '20 08:04 linkyndy

@linkyndy Would you like to tackle that? You can get some inspiration from recent commits in rspec-expectations.

PS Not sure if this works as intended:

expect(item).to eq(item)

pirj avatar Apr 13 '20 09:04 pirj

What are "# ...other expectations..." exactly? Won't it be sufficient to expect(double).to receive(...).with(...).and_call_original instead if all your expectations are made on arguments? Will you get the same deprecation message when specifying with(item: item)?

pirj avatar Apr 13 '20 09:04 pirj

Thanks for your quick answer @pirj! I would love to tackle that, however I can't consider that one of my priorities at the moment, unfortunately.

I've updated my snippet. The other expectations are related to the double that's yielded to the given block. I could stub method to yield another_double and have all expectations linear, rather than nested, indeed.

Thanks for pointing out the silly first expectation, also! 😊

linkyndy avatar Apr 13 '20 09:04 linkyndy

can't consider that one of my priorities at the moment, unfortunately.

No rush, we're slowly moving there, no work on rspec-mocks has been done yet.

expect(another_double).to receive(:another_method)

I believe you can move this out of the block and it will have the same effect:

expect(double).to receive(:method) do |item:, &block|
  expect(item).to eq(item_double)
  # ...other expectations...
  block.call(another_double)
end
expect(another_double).to receive(:another_method)

This will get you closer to with(...) option.

pirj avatar Apr 13 '20 10:04 pirj

Yes, I did it that way and removed the block altogether. I thought it was more expressive with the block, but it's not that big of a difference. Thanks!

I think we can keep this issue open, to actually solve the Ruby warning at some point.

linkyndy avatar Apr 13 '20 11:04 linkyndy

I think I am running into this same issue. I'm getting:

/home/josh/.rvm/gems/ruby-2.7.0/gems/rspec-mocks-3.9.1/lib/rspec/mocks/message_expectation.rb:694: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call

With a spec like this:

allow(File).to receive(:read) do |*args, **kwargs|
  if args.first == "special"
    ""
  else
    IO.read(*args, **kwargs)
  end
end

(in this test I wanted to handle a certain file in a special way but actually read the other files)

holtrop avatar Sep 04 '20 18:09 holtrop

Most likely you are, sorry! We are working on this but its complicated to fix even through its just a warning.

JonRowe avatar Sep 04 '20 20:09 JonRowe