If you try to run the test suite after adding a child process that has a mocked dependency, you will end up with something like this:
** (UndefinedFunctionError) function MyModule.Mock.function/0 is undefined (module MyModule.Mock is not available)
The reason is that the process is started before the mock is defined. We could move the mock definition at compile-time, but we would end up with something like this anyway:
** (Mox.UnexpectedCallError) no expectation defined for MyModule.Mock.function/0 in process #PID<0.1029.0> with args []
This time, the reason is that the expectations are process based. The child process does not have access to the mock.
First, only inject the process in non-test environments. In my case, it was a GenServer. Simply use config files to achieve it:
application.ex
children = Application.get_env(:app, :children)
config/config.exs
config :app, :children, [MyApp.GenServer]
config/test.exs
config :app, :children, []
Now you will need to configure your test to allow access to the mock. Then you can manually start you process.
my_app/gen_server_test.exs
defmodule MyApp.GenServerTest do
# An ExUnit case where tests use Mox in global mode cannot be async: true.
use ExUnit.CaseTemplate, async: false
setup do
# https://hexdocs.pm/mox/Mox.html#set_mox_global/1
# In global mode, mocks can be consumed by any process.
Hammox.set_mox_global()
Hammox.verify_on_exit!()
end
test "test" do
Hammox.expect(MyModule.Mock, :function, fn ->
...
end)
start_supervised!(MyApp.GenServer)
...
end
end
Happy testing! 🎉