-
-
Notifications
You must be signed in to change notification settings - Fork 358
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
3.11.1 breaks argument matching in Ruby 2.7 #1466
Comments
Unless I'm missing something, the issue with class A
def foo(a1, a2, bang: 5, baz: nil)
puts [a1, a2, bang, baz].inspect
end
end
def call(client, name, *args, **kwargs)
client.public_send(name, *args, **kwargs)
end
call(A.new, :foo, 'a', 1) # => ["a", 1, 5, nil]
call(A.new, :foo, 'a', 1, baz: 5) # => ["a", 1, 5, 5] Interestingly, if I switch |
If you debug it, args passed to the double are it 'works' do
expect(client).to receive(:foo).with('a', 1, {})
call(client, :foo, 'a', 1)
end |
That's what RSpec is catching, but as I noted before using an |
It is not specific to RSpec, it is how keyword delegation with ef call(client, name, *args)
client.public_send(name, *args)
end
ruby2_keywords :call
RSpec.describe 'args broken' do
let(:client) { double('@client') }
it 'works' do
expect(client).to receive(:foo).with('a', 1)
call(client, :foo, 'a', 1)
end
end the example will pass just fine. |
Speaking of If you turn on doubled constant verification like RSpec.configure do |config|
config.mock_with :rspec do |mocks|
mocks.verify_doubled_constant_names = true
end
end
def call(client, name, *args, **kwargs)
client.public_send(name, *args, **kwargs)
end
RSpec.describe 'args broken' do
let(:client) { instance_double('@client') }
it 'works' do
expect(client).to receive(:foo).with('a', 1)
call(client, :foo, 'a', 1)
end
end the example will fail with:
Which is an expected outcome:
I'd guess that the fact that the example with |
Hey, I came across a similar issue when upgrading rspec-mocks on a Ruby 2.7 app, using method delegation with warts like this fails with a weird NoMethodError: require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'rspec', '= 3.11'
end
require 'rspec/autorun'
class Foo
def bar(zomg, lol: nil)
puts [zomg, lol].inspect
end
def delegate_bar(zomg, **kwargs)
bar(zomg, **kwargs)
end
end
RSpec.describe do
it do
expect_any_instance_of(Foo).to receive(:bar).with(:oops).and_call_original
foo = Foo.new
foo.delegate_bar(:oops)
end
it do
expect_any_instance_of(Foo).to receive(:bar).with(:oops, lol: 'boom').and_call_original
foo = Foo.new
foo.delegate_bar(:oops, lol: 'boom')
end
end
As you can see, the first method that doesn't pass any kwargs fail. My understanding is that the delegation should be changed to use Even though we have a number of places using **kwargs for delegation, which I'll probably have to review, only a handful of specs really failed... I'm guessing just the handful that are testing specifically Thanks! |
@carlosantoniodasilva All valid points. Thanks for reporting. I believe the problem hides here and here. This is causing I don't have a solution to how to make the error message less confusing in this case. |
Subject of the issue
When delegating using
**kwargs
, the spec fails when passed no keyword arguments in 2.7 (no issues with 3.0).Your environment
Steps to reproduce
Expected behavior
Actual behavior
The text was updated successfully, but these errors were encountered: