Named processes can be a bit of a pain to test if you need to setup data before they start.
If you try to start a named process in test, you will get an :already_started error.
There is a great pattern here that @jowensboggs from the Elixir slack channel tipped me off on.
The example here is when trying to merge commands from two timelines into a unified view, we want to test if any commands are due from one of the queues.
You can define the start_link method in your gen_server so that it inspects the args passed, and tries to extract the name, or falls back to __MODULE__.
def start_link(opts) do {name, opts} = Keyword.pop(opts, :name, __MODULE__) init_args = opts GenServer.start_link(__MODULE__, init_args, name: name) end
then in your test you pass the name as a genserver argument:
{:ok, pid} = start_supervised({ShiftSchedule.Worker, name: :my_test})
Finally, in your public API, you would need to optionally accept a pid:
def commands_in_range(%DateTime{} = from, %DateTime{} = to, pid \\ ShiftSchedule.Worker) do GenServer.call(pid, {:get_commands_in_range, from, to}) end
This lets you use __MODULE__ in the rest of your code base, while setting up any data needed for the process before starting it in your tests. Before this I was killing the processes so that the supervisor would restart it which is not good!