Open TonyCTHsu opened 1 year ago
Does it work the same way with other methods, not initialize
/new
?
Interestingly I tried this on Mac (ruby 3.2.0preview2 (2022-09-09 master 35cfc9a3bb) [arm64-darwin21]
) and it passed, so I'm inclined to close this for now as a Ruby bug especially as its not an expected change in behaviour...
Hey @pirj and @JonRowe thanks for the feedback! I work with @TonyCTHsu and he's off for a few weeks, so I can jump in and provide the extra information.
Does it work the same way with other methods, not initialize/new?
Yes! See my provided extended example below.
Interestingly I tried this on Mac (ruby 3.2.0preview2 (2022-09-09 master 35cfc9a3bb) [arm64-darwin21]) and it passed, so I'm inclined to close this for now as a Ruby bug especially as its not an expected change in behaviour...
I suspect it may be a deliberate incompatible Ruby change, as the 3.2.0-preview2 release notes mention it https://www.ruby-lang.org/en/news/2022/09/09/ruby-3-2-0-preview2-released/ ("Methods taking a rest parameter (like args) and wishing to delegate keyword arguments through foo(args) must now be marked with ruby2_keywords (if not already the case). [...]").
You are right re: the reproduction, I remembered Tony showing me the issue and when I just re-ran it locally I was actually not seeing it trigger.
It turns out the reproduction example is incomplete. In particular, mocks.verify_partial_doubles = true
needs to be set in the configuration to trigger the issue -- without it, the issue does not trigger.
Here is an extended example that is self-contained and reproduces on my machine. I can reproduce the issue with:
ruby 3.2.0preview2 (2022-09-09 master 35cfc9a3bb) [x86_64-darwin20]
ruby 3.2.0dev (2022-09-21T13:59:45Z master c21f820b49) [x86_64-darwin20]
(freshly compiled today)ruby 3.2.0preview2 (2022-09-09 master 35cfc9a3bb) [x86_64-linux]
ruby 3.2.0preview2 (2022-09-09 master 35cfc9a3bb) [aarch64-linux]
so it seems to affect every release at least >= 3.2.0-preview2.
Full reproduction:
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'rspec', '= 3.11.0'
end
require 'rspec/autorun'
puts RUBY_DESCRIPTION
RSpec.configure do |config|
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true # changing this to false makes the issue go away
end
end
RSpec.describe do
class TestObject
def initialize(**kwargs)
end
def foo(**kwargs)
end
end
context 'TestObject.new' do
it 'double splat block args' do
expect(TestObject).to receive(:new) do |**opts|
expect(opts).to eq(foo: 'bar')
end
hash = { foo: 'bar' }
TestObject.new(**hash)
end
it 'keyword block args' do
expect(TestObject).to receive(:new) do |foo:, **_|
expect(foo).to eq('bar')
end
hash = { foo: 'bar' }
TestObject.new(**hash)
end
end
context 'TestObject#foo' do
let(:instance) { TestObject.new }
it 'double splat block args' do
expect(instance).to receive(:foo) do |**opts|
expect(opts).to eq(foo: 'bar')
end
hash = { foo: 'bar' }
instance.foo(**hash)
end
it 'keyword block args' do
expect(instance).to receive(:foo) do |foo:, **_|
expect(foo).to eq('bar')
end
hash = { foo: 'bar' }
instance.foo(**hash)
end
end
end
Subject of the issue
Message expectation with block arguments for keyword argument method behaves differently for
ruby 3.2.0preview2
.The code snippets works fine with ruby
3.0.3
and ruby3.1.1
. I wasn't sure what is the root cause.Your environment
Steps to reproduce
Expected behavior
The test passes like
Actual behavior