ExUnit: Testing Named Processes

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)

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})

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!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s