View Source Hammox (Hammox v0.7.0)

Hammox is a library for rigorous unit testing using mocks, explicit behaviours and contract tests.

See the README page for usage guide and examples.

Most of the functions in this module come from Mox for backwards compatibility. As of v0.1.0, the only Hammox-specific functions are protect/2 and protect/3.

Link to this section Summary

Link to this section Types

@type function_arity_pair() :: {atom(), arity() | [arity()]}

Link to this section Functions

Link to this function

allow(mock, owner_pid, allowed_via)

View Source

See Mox.allow/3.

See Mox.defmock/2.

Link to this function

expect(mock, function_name, n \\ 1, code)

View Source

See Mox.expect/4.

Link to this function

protect(module)

View Source (since 0.1.0)
@spec protect(module :: module()) :: %{required(atom()) => (... -> any())}
@spec protect(mfa :: mfa()) :: (... -> any())

See protect/3.

Link to this function

protect(mfa, behaviour_name)

View Source (since 0.1.0)
@spec protect(module :: module(), funs :: [function_arity_pair()]) :: %{
  required(atom()) => (... -> any())
}
@spec protect(mfa :: mfa(), behaviour_name :: module()) :: (... -> any())
@spec protect(implementation_name :: module(), behaviour_name :: module()) :: %{
  required(atom()) => (... -> any())
}

See protect/3.

Link to this function

protect(module, behaviour_name, funs)

View Source (since 0.1.0)
@spec protect(
  module :: module(),
  behaviour_name :: module(),
  funs :: [function_arity_pair()]
) :: %{required(atom()) => (... -> any())}

Decorates functions with Hammox checks based on given behaviour.

basic-usage

Basic usage

When passed an MFA tuple representing the function you'd like to protect, and a behaviour containing a callback for the function, it returns a new anonymous function that raises Hammox.TypeMatchError when called incorrectly or when it returns an incorrect value.

Example:

defmodule Calculator do
  @callback add(integer(), integer()) :: integer()
end

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

add_2 = Hammox.protect({TestCalculator, :add, 2}, Calculator)

add_2.(1.5, 2.5) # throws Hammox.TypeMatchError

batch-usage

Batch usage

You can decorate all functions defined by a given behaviour by passing an implementation module and a behaviour module. Optionally, you can pass an explicit list of functions as the third argument.

The returned map is useful as the return value for a test setup callback to set test context for all tests to use.

Example:

defmodule Calculator do
  @callback add(integer(), integer()) :: integer()
  @callback add(integer(), integer(), integer()) :: integer()
  @callback add(integer(), integer(), integer(), integer()) :: integer()
  @callback multiply(integer(), integer()) :: integer()
end

defmodule TestCalculator do
  def add(a, b), do: a + b
  def add(a, b, c), do: a + b + c
  def add(a, b, c, d), do: a + b + c + d
  def multiply(a, b), do: a * b
end

%{
  add_2: add_2,
  add_3: add_3,
  add_4: add_4
  multiply_2: multiply_2
} = Hammox.protect(TestCalculator, Calculator)

# optionally
%{
  add_2: add_2,
  add_3: add_3,
  multiply_2: multiply_2
} = Hammox.protect(TestCalculator, Calculator, add: [2, 3], multiply: 2)

batch-usage-for-multiple-behviours

Batch usage for multiple behviours

You can decorate all functions defined by any number of behaviours by passing an implementation module and a list of behaviour modules.

The returned map is useful as the return value for a test setup callback to set test context for all tests to use.

Example:

defmodule Calculator do
  @callback add(integer(), integer()) :: integer()
  @callback multiply(integer(), integer()) :: integer()
end

defmodule AdditionalCalculator do
  @callback subtract(integer(), integer()) :: integer()
end

defmodule TestCalculator do
  def add(a, b), do: a + b
  def multiply(a, b), do: a * b
  def subtract(a, b), do: a - b
end

%{
  add_2: add_2,
  multiply_2: multiply_2
  subtract_2: subtract_2
} = Hammox.protect(TestCalculator, [Calculator, AdditionalCalculator])

behaviour-implementation-shortcuts

Behaviour-implementation shortcuts

Often, there exists one "default" implementation for a behaviour. A common practice is then to define both the callbacks and the implementations in one module. For these behaviour-implementation modules, Hammox provides shortucts that only require one module.

Example:

defmodule Calculator do
  @callback add(integer(), integer()) :: integer()
  def add(a, b), do: a + b
end

Hammox.protect({Calculator, :add, 2})
# is equivalent to
Hammox.protect({Calculator, :add, 2}, Calculator)

Hammox.protect(Calculator, add: 2)
# is equivalent to
Hammox.protect(Calculator, Calculator, add: 2)

Hammox.protect(Calculator)
# is equivalent to
Hammox.protect(Calculator, Calculator)
Link to this function

set_mox_from_context(context)

View Source

See Mox.set_mox_from_context/1.

Link to this function

set_mox_global(context \\ %{})

View Source

See Mox.set_mox_global/1.

Link to this function

set_mox_private(context \\ %{})

View Source

See Mox.set_mox_private/1.

Link to this function

stub(mock, function_name, code)

View Source

See Mox.stub/3.

See Mox.stub_with/2.

See Mox.verify!/0.

See Mox.verify!/1.

Link to this function

verify_on_exit!(context \\ %{})

View Source

See Mox.verify_on_exit!/1.