Search code examples
rubymockingminitest

minitest - mock - expect keyword arguments


When I want to verify that mock is send expected arguments, I can do

@mock.expect(:fnc, nil, ["a, "b"])

however, if class I want to mock looks like this

class Foo
    def fnc a:, b:
    end
end

how can I mock it and verify values passed as a:, b:?


Solution

  • Below is a real-world example from my company's codebase:

    mailer = MiniTest::Mock.new
    mailer.expect :deliver, 123 do |template_name:, data:, to:, subject:|
      true
    end
    mailer.deliver template_name: "xxx", data: {}, to: [], subject: "yyy"
    

    If you also want to verify arguments' types:

    mailer.expect :deliver, 123 do |template_name:, data:, to:, subject:|
      template_name.is_a?(String) &&
        data.is_a?(Hash) &&
        to.is_a?(Array) &&
        subject.is_a?(String) &&
    end
    

    Update 2022-05-22

    You would get ArgumentError if you use this strategy with Ruby v3.

    I have submitted a PR here to fix this issue:

    https://github.com/minitest/minitest/pull/908

    If you wish to use this feature with Ruby v3, please leave some comments to get project owner's attention.

    Update 2022-06-28

    minitest supports keyword arguments since v5.16.0 🎉

    https://github.com/minitest/minitest/blob/master/History.rdoc#5160--2022-06-14-