I'm trying to use Minitest mocks to verify a call to a method that expects keyword arguments; but, I'm getting this error:
ArgumentError: wrong number of arguments (given 4, expected 2..3)
This is my complete test:
test ".toggle updates the category" do
mock = Minitest::Mock.new
mock.expect :update!, nil, [], {collapsed: true}
CategoryAnalyzer.toggle_category(mock, true)
mock.verify
end
This is the method under test:
def self.toggle_category(category, collapsed)
category.update!(collapsed: collapsed)
end
I see from minitest - mock - expect keyword arguments that Minitest should accept keyword arguments. Is my test set up wrong? Do I somehow have an old version of Minitest? (My Gemfile.lock
lists minitest (5.18.0)
) Any idea of what else I should check?
This is how you're calling expect
, with 4 arguments:
# 1 2 3 4
mock.expect :update!, nil, [], {collapsed: true}
This is what it expects:
# 1 2 3 keywords block
def expect name, retval, args = [], **kwargs, &blk
Since ruby v3.0 {collapsed: true}
is a positional argument. To turn it into keywords, you have to **
splat or just drop the braces:
# 1 2 3 keywords
mock.expect :update!, nil, [], collapsed: true
# or this
mock.expect :update!, nil, [], **{collapsed: true}
kw = {collapsed: true}
mock.expect :update!, nil, [], **kw
A simple demo:
def arg_or_kwarg(one = nil, two = nil, **kwargs)
{one: one, two: two, kwargs: kwargs}
end
# pass argument #1
>> arg_or_kwarg({hash: :arg})
=> {:one=>{:hash=>:arg}, :two=>nil, :kwargs=>{}}
# pass keyword argument
>> arg_or_kwarg(kw: :arg)
=> {:one=>nil, :two=>nil, :kwargs=>{:kw=>:arg}}