Open honigc opened 2 years ago
This is at least partially fixed by https://github.com/rspec/rspec-mocks/pull/1473 (when with
is used to set up the stub, ArgumentError
isn't raised but RSpec::Mocks::MockExpectationError
is) so if the answer is to just wait for that to be released, I'd understand. When with
is not used, though, there's still something I find confusing even with 1473 applied:
it do
instance = instance_double(klass)
# .with is not used for the stub
allow(instance).to receive(:m)
# These pass, showing that arguments are verified at least a little bit
expect { instance.m(:totally_wrong) }.to raise_error(ArgumentError)
expect { instance.m(wrong: "value") }.to raise_error(ArgumentError)
expect { instance.m({ wrong: "value" }) }.to raise_error(ArgumentError)
# Fails
expect { instance.m({ keyword: "value" }) }.to raise_error(StandardError)
end
I'm running into this with the latest rspec-mocks (version 3.12.5). It's making the upgrade from Ruby 2.7 to 3.x, extra painful.
When
with
is not used, though, there's still something I find confusing even with 1473 applied:
@honigc - could you elaborate here? Is the confusing bit that RSpec::Mocks::MockExpectationError
is not a subclass of StandardError
? (I assume that's necessary for the broad error-handling rspec has to do to properly catch and expose the exceptions produced by the code under test as being separate from the exceptions produced by the mocks/matchers)
I'm curious if there's still any change needed here.
I assume that's necessary for the broad error-handling rspec has to do to properly catch and expose the exceptions produced by the code under test as being separate from the exceptions produced by the mocks/matchers
Correct, it is because rescue
by default catches StandardError
, so we raise errors inherited from Exception
to try to avoid your code swallowing spec failures.
Subject of the issue
When using an
instance_double
of a class that defines an instance method that takes keyword arguments, then usingallow
orexpect
to stub that method in the verifying double, the method can be called on the verifying double with either keywords or a Hash object passed. This happens whether or notwith
is used when setting up the stub.When using live objects, passing a Hash without a double-splat raises
ArgumentError
in Ruby 3 while it worked fine in Ruby 2.7. The fact that tests don't fail in this situation in Ruby 3 has made upgrading Ruby in a large project more complicated.Your environment
Steps to reproduce
Expected behavior
Actual behavior