At the time of this writing, I have tested all major mocking libraries (Mock, Mox and Mimic).
Both Mock and Mimic rely on :meck
underneath. Rather surprisingly, I get the exact same issue with Mimic as I got with Mock, i.e., the process crashes without warning.
This leaves me to the only logical conclusion, which is that the problem I am facing is related to the underlying system that servers as a base for both libraries: :meck
. This issue does not happen using Mox.
I have therefore decided not to use Mock (nor Mimic) for the application and I am instead injecting the dependencies directly into the functions that need them. This last approach is very lightweight and does allow for async: true
which gives a noticeable speed increase when running mix test
.
Because I am only using a very small portion of the external system’s API (2 - 3 functions) this fits well with my needs. However, If I were to use all functions from said API (let’s say 20) this solution would be rather difficult to manage.
I don’t expect the affected modules to evolve in such a direction, so for the time being, I am rather happy.
Here is a sample test for those searching for inspiration (using File
as an example):
setup do
%{
paths: [products: ["products.json"]]
}
end
test "returns list of available products from given syndicate", %{paths: paths} = deps do
read_fn = fn filename ->
assert filename == Path.join(paths[:products])
{:ok, "[{\"name\": \"utc\"}]"}
end
deps = Map.put(deps, :io, %{read: read_fn})
syndicate = Syndicate.new(name: "UTC", id: :utc)
assert FileSystem.list_products(syndicate, deps) ==
{:ok, [Product.new(%{"name" => "Bananas"})]}
end