Resolve an issue using method doubles with keyword arguments on Ruby 3#1385
Conversation
|
Well this approach clearly has some issues for Ruby < 2.7. |
|
1f2d12b fixes some of the test failures, but I'd prefer to use the ruby2_keywords shim. Are we okay adding that dependency? |
| define_method(method_name) do |*args, &block| | ||
| method_double.proxy_method_invoked(self, *args, &block) | ||
| end | ||
| ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true) |
There was a problem hiding this comment.
@bryanp 👏
Just wondering how did you figure it out? 2.7.1's warning traces are kind of unhelpful.
There was a problem hiding this comment.
@pirj I found a test case that raised an exception, so there was a pretty strong hint in the backtrace:
ArgumentError:
wrong number of arguments (given 1, expected 0; required keyword: bar)
# ./spec/rspec/mocks/and_call_original_spec.rb:189:in `foo'
# ./lib/rspec/mocks/message_expectation.rb:101:in `call'
# ./lib/rspec/mocks/message_expectation.rb:101:in `block in and_call_original'
# ./lib/rspec/mocks/message_expectation.rb:740:in `call'
# ./lib/rspec/mocks/message_expectation.rb:572:in `invoke_incrementing_actual_calls_by'
# ./lib/rspec/mocks/message_expectation.rb:427:in `invoke'
# ./lib/rspec/mocks/proxy.rb:217:in `message_received'
# ./lib/rspec/mocks/proxy.rb:361:in `message_received'
# ./lib/rspec/mocks/method_double.rb:78:in `proxy_method_invoked'
# ./lib/rspec/mocks/method_double.rb:64:in `block (2 levels) in define_proxy_method'
# ./spec/rspec/mocks/and_call_original_spec.rb:191:in `block (3 levels) in <top (required)>'
There was a problem hiding this comment.
Ah yes, sadly 2.7 is less helpful
There was a problem hiding this comment.
Sorry for the inconvenience 🙏
Just a tip: if you run it on Ruby 3.0, it will raise an exception instead of a warning, which will show a more helpful backtrace.
| def instance.foo(bar:); bar; end | ||
| expect(instance).to receive(:foo).and_call_original | ||
| expect(instance.foo(bar: "baz")).to eq("baz") | ||
| end |
There was a problem hiding this comment.
This needs to be wrapped in an eval for our older ruby test suite, and skipped when theres no keyword argument support. (RSpec 3 supports 1.8.7 up).
There was a problem hiding this comment.
|
Triggered a dummy build to figure out if those failures are due to the change or unrelated #1386 |
|
Addressed feedback so far but still getting failures that seem unrelated to my change. Ideas? |
|
So the build failure is from this change, I can reproduce it on a clean build with only that line changing (spec failed 3.0 and 2.7 but passed 2.5 2.6, add that one line and 3.0 and 2.7 pass but 2.5 2.6 fails) The why still escapes me for the moment. |
|
Have you reproduced the failures locally? I've only seen them on CI so far. |
|
@bryanp yes, they are from rspec-rails when combined with this branch |
|
@JonRowe What's the best way to locally run the |
|
@bryanp The RSpec repos will automatically run against the local version that sits in a folder next to them, e.g. if you have: Doing a bundle install in rspec-rails and then running the specs should fail if you have this branch checked out on rspec-mocks. I am going to look at this when I have the time, but if you beat me to it I will be ecstatic :) |
|
Aha, finally reproduced the failure. I'm looking specifically at this one: Here's the important part of the failure: Couple of observations:
I don't yet understand how |
|
@bryanp Interesting! Or probably use |
|
I have some serious problem understanding what is going on in that gem while looking at this line 😄 I don't mind either option. To me, @mame, can you please advise what is the best option for our case? In order to avoid that |
|
We do use the "unbind the real method and use that" to work around monkey patching in various places, maybe we need that trick in |
|
Hello! I think Sorry, the check in |
|
Thank you @mame for you input. I've made the suggested change. This resolved the issues in Ruby 2.* but 1.8.7 and 1.9.2 are still failing in Travis. I haven't looked into why yet. |
|
Looks like this issue is unrelated to this PR, this time for sure? https://travis-ci.org/github/rspec/rspec-mocks/jobs/753288703 |
Using `respond_to?` causes issues in rspec-rails because of how the `Railtie` class implements `respond_to_missing?`.
85504da to
2ca170b
Compare
|
There were some changes to |
|
Travis is broken and I'm replacing the builds as I can. |
Resolve an issue using method doubles with keyword arguments on Ruby 3
Resolve an issue using method doubles with keyword arguments on Ruby 3
…rgs-for-ruby3 Resolve an issue using method doubles with keyword arguments on Ruby 3 --- This commit was imported from rspec/rspec-mocks@117b33d.
This commit was imported from rspec/rspec-mocks@ea4d8ea.
…rgs-for-ruby3 Resolve an issue using method doubles with keyword arguments on Ruby 3 --- This commit was imported from rspec/rspec-mocks@a0f33ee.
This commit was imported from rspec/rspec-mocks@b843db7.
…rgs-for-ruby3 Resolve an issue using method doubles with keyword arguments on Ruby 3 --- This commit was imported from rspec/rspec-mocks@0306f46.
|
I've run into this weird issue with For some reason it only happens on 2.5/2.6, I guess because 1) 2.7+ have the methods, so don't fall into the trap, and 2) only those Ruby versions test the Rails version with this weird behavior? (which still exists on Rails main) |
FWIW, that was fine and no bug, it finds Module#ruby2_keywords, since it's called on the Module class, which is a module (as all classes are). |
|
I've filed an issue to Rails about this, and found at least one spot where they unintentionally create a Railtie instance by a |
This captures and resolves an issue I encountered when running my test suite on Ruby 3. It may resolve more issues than just with
and_call_originalbut that needs more investigation. Happy to fill in more test cases here but I haven't gone through to see what else usesMethodDoubleyet.