Packages

ExStub provides an easy way to stub a module to facilitate writing clean, isolated unit tests.

Current section

Files

Jump to
ex_stub lib ex_stub_assert.ex
Raw

lib/ex_stub_assert.ex

defmodule ExStub.Assert do
@moduledoc """
This module provides the `assert_called` that can be used to assert functions calls on your stubs.
This module is already required and imported when using `use ExStub`
"""
@doc """
Asserts that the function was called on the module with the passed params.
The syntax is `assert_called ModuleName.function_name(params)`
```elixir
assert_called ModuleName.function_name()
assert_called ModuleName.function_name(nil)
assert_called ModuleName.function_name(1, 2)
```
## Example
```elixir
defstub MyStub, for: OriginalModule do
def process(1), do: :stubbed3
end
MyStub.process(1)
# Passes since we called the function with [1]
MyStub.process(1)
# Fails since the parameters dont match
MyStub.process(1, 2)
# Fails since we did not call `another_method`
MyStub.another_method()
```
"""
defmacro assert_called(call) do
{{:., _, [module, function]}, _, params} = call
mod_name = module_name_from_ast(module)
assert_call_macro(mod_name, function, params)
end
defp assert_call_macro(mod_name, func_name, params) do
quote do
res = check_called(unquote(mod_name),unquote(func_name), unquote(params))
if res != :ok do
flunk res
end
end
end
def check_called(mod_name, func_name, params) do
ExStub.Recorder.calls(mod_name, func_name, params)
|> check_success(mod_name, func_name, params)
end
defp check_success([], mod_name, func_name, params) do
"Expected call to `#{inspect(mod_name)}.#{func_name |> Atom.to_string}` with #{inspect(params)} was not recorded"
end
defp check_success(_, _, _, _) do
:ok
end
defp module_name_from_ast(ast_module_name), do: Code.eval_quoted(ast_module_name) |> elem(0)
end