Mocks dont raise keyword argument errors
Created by: pedrocarmona
Subject of the issue
When preparing for ruby 3, I want the following deprecation warnings to be thrown when using mocks, so that I can update the code:
Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
Your environment
- Ruby version: 2.7.2
- rspec-mocks version: 3.10.2
configure application to show deprecations
via env variable:
RUBYOPT='-W:deprecated'
or add to config/environments/test.rb
Warning[:deprecated] = true
Steps to reproduce
describe "#thing" do
let(:something) { instance_double(Something) }
before do
allow(Something).to receive(:new).and_return(something)
end
it "initializes something" do
subject
expect(Something).to have_received(:new).with(
a: :b
)
end
end
Expected behavior
Moreover, I would expect it to fail in ruby 3 (as the code would not be executed in production).
and the block version can detect the kwargs problem, so it should work like it:
describe "#thing" do
let(:something) { instance_double(Something) }
before do
allow(Something).to receive(:new).and_return(something)
end
it "initializes something" do
subject
expect(Something).to have_received(:new) do |*args, **kwargs|
expect(kwargs).to match({a: :b})
end
end
end
When using this approach we can correctly detect deprecated version ^
Actual behavior
All tests pass
Fix
monkey patching allows to throw errors
module RSpec
module Mocks
module Matchers
class HaveReceived
alias_method :original_with, :with
def with(*args, **kwargs)
@block ||= proc do |*w_args, **w_kwargs|
# enforce keyword args
end
original_with(*args, **kwargs)
end
end
end
end
end