Mox
Functional mocking microlibrary
ElixirConf EU 2018, by @hubertlepicki
@hubertlepicki
ElixirConf EU 2018, by @hubertlepicki
https://slides.com/
hubertlepicki
ElixirConf EU 2018, by @hubertlepicki
Mox
github.com/plataformatec/mox
ElixirConf EU 2018, by @hubertlepicki
Mox is a functional mocking microlibrary based on the idea of smart explicit contracts and Ethereum
ElixirConf EU 2018, by @hubertlepicki
by José Valim, Plataformatec blog, 2015
ElixirConf EU 2018, by @hubertlepicki
Feature missing: help needed
ElixirConf EU 2018, by @hubertlepicki
Hubert, José's Minion
ElixirConf EU 2018, by @hubertlepicki
Mox principles
-
No ad-hoc mocks. You can only create mocks based on behaviours
-
No dynamic generation of modules during tests. Mocks are preferably defined in your test_helper.exs or in a setup_all block and not per test (I disagree!)
-
Concurrency support. Tests using the same mock can still use async: true
-
Rely on pattern matching and function clauses for asserting on the input instead of complex expectation rules
ElixirConf EU 2018, by @hubertlepicki
Define behaviour & code
Declare mock
ElixirConf EU 2018, by @hubertlepicki
defmodule CalcBehaviour do
@callback multiply(integer(), integer()) :: integer()
end
defmodule Calc do
@behaviour CalcBehaviour
def multiply(a, b), do: a * b end
end
test/support/mocks.ex
defmock CalcMock, for: CalcBehaviour
config.exs
test.exs
ElixirConf EU 2018, by @hubertlepicki
Application.put_env(
:my_app,
:calc,
Calc
)
Application.put_env(
:my_app,
:calc,
CalcMock
)
In your config/...
In your app code...
ElixirConf EU 2018, by @hubertlepicki
defmodule Rectangle do
@calc Application.get_env(:my_app, :calc)
def area(width, height) do
@calc.multiply(width, height)
end
end
In your tests code...
ElixirConf EU 2018, by @hubertlepicki
setup :verify_on_exit!
test "computes area with current math rules" do
CalcMock
|> expect(:multiply, fn 2, y -> 2 + y end)
assert Rectangle.area(2, 3) == 5
end
In your tests code...
ElixirConf EU 2018, by @hubertlepicki
setup :verify_on_exit!
test "computes area with current math rules" do
CalcMock
|> stub(:multiply, fn 2, y -> 2 + y end)
assert Rectangle.area(2, 3) == 5
end
Other goodies
- set_mox_private/1
- set_mox_global/1
- set_mox_from_context/1
- allow/3
- verify_on_exit/1
- verify!
Code: Done
Try mox!
Thanks!
Mox
By Hubert Łępicki
Mox
- 1,595