Closed benoittgt closed 1 year ago
CI failures seems to be unrelated. I will look at them separately on rspec-support
. Probably https://github.com/rspec/rspec-support/pull/553 and https://github.com/rspec/rspec-support/pull/555
This branch fixes my test suite on Ruby 3.2. 👍
I dared pushing a commit that makes the kwargs vs positional options hash check more strict.
TODO:
spec/rspec/mocks/matchers/receive_spec.rb
fails for some weird reason similar to the one described above in spec/rspec/mocks/argument_matchers_spec.rb
, but I couldn't quickly find a workaround the same way I did for spec/rspec/mocks/argument_matchers_spec.rb
MethodDouble
the Proxy called raise_unexpected_message_args_error
instead of raise_unexpected_message_error
the same way it does in other cases when there's a message expectation, but arguments don't match@paddor May I kindly ask you to repeat your test after the last commit?
https://github.com/rspec/rspec-core/pull/2993 is needed to make the CI green(er) for rspec-core
sub-build.
@pirj It mostly passes. Some #receive_message_chain
-lines with kwargs fail:
#<Double (anonymous)> received unexpected message :store_event with ({:message=>"core.system_events.force_variables", :object=>{:note=>nil, :release_at=>nil, :variable=>{:code=>nil, :desc_i18n=>nil, :label=>nil, :label_i18n=>nil}}, :username=>nil})
Note that the call-site correctly specified these arguments as keywords, not as a Hash.
If I refactor them to use #receive
with intermediate spy-objects, the whole testsuite passes.
@pirj I think it would be safer to ~revert~ remove that strict check (i.e., stricter than Ruby itself is), see https://github.com/rspec/rspec-mocks/pull/1514#discussion_r1060563272. Otherwise it sounds like a huge backward-incompatible change for something which doesn't really gain anything.
@eregon The check is certainly stricter now for def foo(options = {})
or def foo(options)
.
But it's not stricter than Ruby's for def foo(**options)
and def foo(bar:)
.
To make a distinction between those two cases, we would have to make ArgumentListMatcher
aware of the method signature.
All those cases are different instance.method(:foo).parameters
:
Class.new { def foo(options); end }.new.method(:foo).parameters # => [[:req, :options]]
Class.new { def foo(options = {}); end }.new.method(:foo).parameters # => [[:opt, :options]]
Class.new { def foo(**options); end }.new.method(:foo).parameters # => [[:keyrest, :options]]
Class.new { def foo(bar:); end }.new.method(:foo).parameters # => [[:keyreq, :bar]]
What is making matter worse is that Ruby was doing weird things with extracting some arguments from the options hash, see e.g. https://github.com/rspec/rspec-support/pull/537
Running this branch fixes all of my mocking issues. Thank you!
This is more of an rspec-rails issue, but I'm noticing a have_enqueued_job
matcher is no longer finding the job.
expect {
get :create, params: {onboarding_signup_id: onboarding_signup_id}
}.to have_enqueued_job(Sendgrid::ListSignupJob).with(
email: user.email, list: OnboardingSignupsController::CURRENT_ONBOARDING_LIST_NAME
)
expected to enqueue exactly 1 jobs, with [{:email=>"clair_mcdermott@example.net", :list=>"PROD Onboarding v1"}], but enqueued 0
Queued jobs:
Sendgrid::ListSignupJob job with [{:email=>"clair_mcdermott@example.net", :list=>"PROD Onboarding v1"}], on queue default
^^^ passes in Ruby 3.1
I've tested this branch but expectations on any keyword argument seem to not work.
require "spec_helper"
class Ex
def self.foo(a:)
puts "Called foo(a: #{a.inspect})"
true
end
end
RSpec.describe "example" do
it "finds no call on single call" do
allow(Ex).to receive(:foo).and_call_original
Ex.foo(a: 1)
# Failure/Error: expect(Ex).to have_received(:foo).with(a: 1)
# (Ex (class)).foo({:a=>1})
# expected: 1 time with arguments: ({:a=>1})
# received: 0 times
expect(Ex).to have_received(:foo).with(a: 1)
end
it "finds other call on two calls, but still fails" do
allow(Ex).to receive(:foo).and_call_original
Ex.foo(a: 1)
Ex.foo(a: 2)
# #<Ex (class)> received :foo with unexpected arguments
# expected: ({:a=>1}) (options hash)
# got: ({:a=>2}) (keyword arguments)
# Diff:
# @@ -1 +1 @@
# -[{:a=>1}]
# +[{:a=>2}]
expect(Ex).to have_received(:foo).with(a: 1)
expect(Ex).to have_received(:foo).with(a: 2)
# Note that just expecting the second call will still fail, but with an
# inverted error message; it will show the first call.
end
end
Now it works with and without the refactorings in my testsuite. 👍
@paddor Just to make sure, do your receive_message_chain
work, too?
@JonRowe I intend to:
rspec-dev
to add Ruby 3.2 to ciThanks for tackling this, would have been nice to wait for my review but as this ended up as a simple one line lib change it's ok, good work on the updated comment too!
Released in 3.12.2
I added the 3.2 builds myself coordinating with 3-12-maintenance, with a temporary suppression of the broken spec, I still think it can be fixed rather than skipped like this.
Also I've now disabled rebase merges on our repos as they've been used accidentally again and it makes cherry picking to maintenance branches a nightmare, we want single commits for PRs (merge or squash only).
It seems there is place where arguments forwarding is not ok.
I continued the work started by @pirj on https://github.com/rspec/rspec-mocks/pull/1497
fixes #1497 fixes #1502 fixes #1495 fixes #1513 fixes #1512
Related: