This project demonstrates a problem using Mox with a supervised singleton style GenServer.
The problem can be briefly summarised as follows:
When a GenServer is added to the static application supervision tree, it will
be started by default. If this GenServer depends on a service which you would
like to replace with a mock in tests, this is only possible if your service is
not invoked during the GenServer start up process, so start_link, init,
handle_continue etc. If you attempt to call your service during any of these
functions, whilst the code may work in production, in tests when a mock is
defined with Mox.defmock call, it is already too late to define an expection.
Here in this project we have:
The mock is defined inside the test, but you could of course define the test in
the test_helper.ex as suggested by the Mox README but this makes no difference to the result.
There are "work arounds" of course, but none are particularly wholesome.
- You could define your own TestMock module, which means it will be defined at the time of application boot.
- You could test for the
Mix.envorfunction_exported?but uggg!! - You could call
mix test --no-startand manually start.
- What is your suggested approach to deal with this?
- Are we testing the wrong abstraction?
- Should we go with a hand crafted mock?
- Are there any other options to solve this?