Method: Mocha::Expectation#with

Defined in:
lib/mocha/expectation.rb

#with(*expected_parameters_or_matchers) {|actual_parameters| ... } ⇒ Expectation

Modifies expectation so that the expected method must be called with expected_parameters_or_matchers.

May be used with Ruby literals or variables for exact matching or with parameter matchers for less-specific matching, e.g. ParameterMatchers::Methods#includes, ParameterMatchers::Methods#has_key, etc. See ParameterMatchers for a list of all available parameter matchers.

Alternatively a block argument can be passed to #with to implement custom parameter matching. The block receives the *actual_parameters as its arguments and should return true if they are acceptable or false otherwise. See the example below where a method is expected to be called with a value divisible by 4. The block argument takes precedence over expected_parameters_or_matchers. The block may be called multiple times per invocation of the expected method and so it should be idempotent.

Note that if #with is called multiple times on the same expectation, the last call takes precedence; other calls are ignored.

Positional arguments were separated from keyword arguments in Ruby v3 (see this article). In relation to this a new configuration option (Configuration#strict_keyword_argument_matching=) is available in Ruby >= 2.7.

When Configuration#strict_keyword_argument_matching= is set to false (which is the default in Ruby v2.7), a positional Hash and a set of keyword arguments passed to #with are treated the same for the purposes of parameter matching. However, a deprecation warning will be displayed if a positional Hash matches a set of keyword arguments or vice versa.

When Configuration#strict_keyword_argument_matching= is set to true (which is the default in Ruby >= v3.0), an actual positional Hash will not match an expected set of keyword arguments; and vice versa, an actual set of keyword arguments will not match an expected positional Hash, i.e. the parameter matching is stricter.

Examples:

Expected method must be called with exact parameter values.

object = mock()
object.expects(:expected_method).with(:param1, :param2)
object.expected_method(:param1, :param2)
# => verify succeeds

object = mock()
object.expects(:expected_method).with(:param1, :param2)
object.expected_method(:param3)
# => verify fails

Expected method must be called with parameters matching parameter matchers.

object = mock()
object.expects(:expected_method).with(includes('string2'), anything)
object.expected_method(['string1', 'string2'], 'any-old-value')
# => verify succeeds

object = mock()
object.expects(:expected_method).with(includes('string2'), anything)
object.expected_method(['string1'], 'any-old-value')
# => verify fails

Loose keyword argument matching (default in Ruby v2.7).


Mocha.configure do |c|
  c.strict_keyword_argument_matching = false
end

class Example
  def foo(a, bar:); end
end

example = Example.new
example.expects(:foo).with('a', bar: 'b')
example.foo('a', { bar: 'b' })
# This passes the test, but would result in an ArgumentError in practice

Strict keyword argument matching (default in Ruby >= 3.0).


Mocha.configure do |c|
  c.strict_keyword_argument_matching = true
end

class Example
  def foo(a, bar:); end
end

example = Example.new
example.expects(:foo).with('a', bar: 'b')
example.foo('a', { bar: 'b' })
# This now fails as expected

Using a block argument to expect the method to be called with a value divisible by 4.

object = mock()
object.expects(:expected_method).with() { |value| value % 4 == 0 }
object.expected_method(16)
# => verify succeeds

object = mock()
object.expects(:expected_method).with() { |value| value % 4 == 0 }
object.expected_method(17)
# => verify fails

Extracting a custom matcher into an instance method on the test class.

class MyTest < Minitest::Test
  def test_expected_method_is_called_with_a_value_divisible_by_4
    object = mock()
    object.expects(:expected_method).with(&method(:divisible_by_4))
    object.expected_method(16)
    # => verify succeeds
  end

  private

  def divisible_by_4(value)
    value % 4 == 0
  end
end

Parameters:

Yields:

  • optional block specifying custom matching.

Yield Parameters:

  • actual_parameters (Array<Object>)

    parameters with which expected method was invoked.

Yield Returns:

  • (Boolean)

    true if actual_parameters are acceptable; false otherwise.

Returns:

See Also:



324
325
326
327
# File 'lib/mocha/expectation.rb', line 324

def with(*expected_parameters_or_matchers, &matching_block)
  @parameters_matcher = ParametersMatcher.new(expected_parameters_or_matchers, self, &matching_block)
  self
end