-
-
Notifications
You must be signed in to change notification settings - Fork 158
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
Mocking a call with empty keyword arguments fails its parameter validation #588
Comments
Thanks for reporting this. I've managed to reproduce the issue under Ruby v2.7 but not under Ruby 3.1. Is that what you're seeing too? My initial reaction is surprise that this test passed with Mocha v1.x since as soon as you call Did you find that surprising too or was it the behaviour you expected? If it was, then can you explain why? |
This was indeed Ruby 2.7, I forgot to mention that. Mocha 1.x on Ruby 2.7 has a few other quirks, the following lines are equivalent: object.expects(:expected_method).with(:param1, :param2, foo: 1)
object.expects(:expected_method).with(:param1, :param2, { foo: 1 }) And for the caller too: object.expected_method(:param1, :param2, foo: 1)
object.expected_method(:param1, :param2, { foo: 1 }) This is the default Ruby 2.x behaviour when using a single splat argument to gather both positional and keyword arguments, so I can guess why and how this worked in Mocha 1.x. |
Thanks for confirming. And thanks for the extra info. I'm still interested in an answer to the question below if you have a chance:
|
That is what I tried to explain with the extra info. If you only use the single splat operator for your argument capture in Ruby 2, the keyword arguments are converted to a hash that is added to the positional keyword arguments:
So I guess I looked at it the other way around: I can guess the implementation based on the behaviour, so the behaviour does not surprise me |
Ah, I see what you mean now. However, rather than thinking about the implementation / the behaviour of Ruby and working backwards, I'm trying to think what would be least surprising to a user of Mocha. Currently I think I'm leaning towards saying that the behaviour of Mocha v1.x in Ruby v2.7 is a bug, because it seems inconsistent / surprising to me. That would suggest releasing a patch version of v1.x to issue a deprecation warning and then another patch version of v1.x to "correct" the behaviour. It also assumes that there's a way to implement the deprecation warning and the correct behaviour - I haven't really thought much about that yet. I think this would mean you would need to change the arguments or matchers in the call to Does that make sense to you? Or am I missing something? |
I guess that would make a backwards incompatible change, which should not happen in a minor release (according to semantic versioning). Also: I'm not sure how well this change would work. The Gemspec for the latest 1.x release of Mocha says the minimal Ruby version is 1.9. Keyword arguments have kind of been a hacked on extension in Ruby for years, I expect this would break things. My personal opinion: Don't change the behaviour of 1.x: it is too much effort and is very likely to break things. I'm not saying this is the best possible behaviour, but it's probably good enough given that nobody ever reported an issue for this behaviour. |
Sorry I haven't updated this issue in a while. I have been thinking about it, but haven't had much time to actually do anything! A small improvement I could make fairly easily would be to change the way method invocations are represented - in particular so that empty keyword arguments are displayed more sensibly. This would at least mean the weird error message you originally reported would make a bit more sense! Currently an invocation with keyword arguments vs a positional Hash are represented like this in error messages: foo.bar(:x => 1) # keyword arguments
foo.bar({:x => 1}) # positional Hash i.e. the only distinction is the presence or absence of surrounding braces. Using the hash-rocket syntax is necessary to cope with the potential for keyword arguments with String keys. However, keyword arguments can be empty, so how about: foo.bar(**{:x => 1}) # keyword arguments
foo.bar({:x => 1}) # positional Hash Then empty keyword arguments would be represented like this: foo.bar(**{}) # keyword arguments
foo.bar({}) # positional Hash The latter seems a bit clunky, but at least it's very explicit. I suppose I could make empty keyword arguments an exception and just use the double-splat for that. Thoughts? |
I think only showing |
I tend to agree. 👍 However, I'm also still not convinced the current approach of using the presence or absence of wrapping braces is a good way to distinguish a keyword |
Given the following code (a slight change from the example of
with
):This worked fine in Mocha 1.x, but this results in a pretty weird error message with Mocha 2.0.2:
When we explicitly add an empty hash to the expectation, we can make the test pass with a warning that tells us to change the code:
With
strict_keyword_argument_matching = true
, both options failThe text was updated successfully, but these errors were encountered: