elixir_mock v0.2.3 ElixirMock.Matchers

Contains utility functions that allow predicate-based matching against arguments passed to mock function calls.

The ElixirMock.assert_called/1 and ElixirMock.refute_called/1 macros can take matchers in place of literal arguments in function call verifications. A matcher is any tuple of the form {:matches, &matcher_fn/1} where matcher_fn is a function of arity 1 that returns a boolean given a value. That value is an argument passed to a call to the mock function in the same position as the matcher as declared in the call verification statement.

Example

defmodule MyTest do
  use ExUnit.Case
  require ElixirMock
  import ElixirMock

  defmodule MyModule do
    def add(a, b), do: a + b
  end

  test "add was called with an even number as the first argument" do
    an_even_number = fn(number) -> rem(number, 2) == 0 end
    mock = mock_of MyModule

    mock.add(4, 3)

    assert_called mock.add({:matches, an_even_number}, 3) # passes
    assert_called mock.add(4, {:matches, an_even_number}) # fails!
  end
end

The ElixirMock.Matchers module contains functions for common matching use cases like matching any argument, matching only number arguments, e.t.c. See this module’s functions list for a list of in-built matchers.

Link to this section Summary

Functions

A matcher that matches any argument

A matcher that matches an argument only if it is of a specified type

A get-out-of-jail matcher that helps you literally match arguments that look like matchers

Link to this section Functions

A matcher that matches any argument.

Use it when you don’t care about some or all arguments in a function call assertion. Also, since ElixirMock.assert_called/1 and ElixirMock.refute_called/1 will not match function calls with different number of arguments from what the assertion specifies, the any/0 matcher is necessary to be able do assertions like the one in the example below

Example:

defmodule MyTest do
  use ExUnit.Case
  require ElixirMock
  import ElixirMock
  alias ElixirMock.Matchers

  defmodule MyModule do
    def echo(arg), do: IO.puts(arg)
  end

  test "echo was called with any argument" do
    mock = mock_of MyModule
    mock.echo("hello")

    # If just want to verify that '&echo/1' was called but I don't care about the arguments:
    assert_called mock.echo(Matchers.any) # passes

    # But this will not pass:
    assert_called mock.echo # fails!
  end
end

A matcher that matches an argument only if it is of a specified type.

Supported types are :atom, :binary, :boolean, :float, :function, :integer, :list, :map, :number, :pid, :tuple and :_ (equivalent to using any/0). An ArgumentError is thrown if an argument not in this list is passed to the function.

Example:

defmodule MyTest do
  use ExUnit.Case
  require ElixirMock
  import ElixirMock
  alias ElixirMock.Matchers

  defmodule MyModule do
    def echo(arg), do: IO.puts(arg)
  end

  test "echo was called with a float" do
    mock = mock_of MyModule

    mock.echo(10.5)

    assert_called mock.echo(Matchers.any(:float)) # passes
    assert_called mock.echo(Matchers.any(:integer)) # fails!
  end
end

A get-out-of-jail matcher that helps you literally match arguments that look like matchers

When ElixirMock finds an argument that looks like {:matches, other_thing} in a function call verification, it will assume that other_thing is a function that is supposed to be used to match an argument. In the rare case that you need to match an argument that is literally {:matches, other_thing}, use this matcher. It will tell ElixirMock not to think about it as a matcher expression but rather as a literal value.

Example:

defmodule MyTest do
  use ExUnit.Case
  require ElixirMock
  import ElixirMock
  alias ElixirMock.Matchers

  defmodule MyModule do
    def echo(arg), do: IO.puts(arg)
  end

  test "echo was called with a float" do
    mock = mock_of MyModule

    mock.echo({:matches, 10})

    assert_called mock.echo(Matchers.literal({:matches, 10})) # passes
    assert_called mock.echo({:matches, 10}) # will blow up!
  end
end