Testing that a GenServer exited

| 1 min read

In the project I'm working on, I need to keep a GenServer up for a while, but I don't want to keep it up forever as I want to free resources.
The solution is to use the timeout mechanism with an handle_info(:timeout, _) callback stoping the loop.

This is straightforward, but then another question came up: How should I test that ?

After digging for a while I discovered that the solution is to monitor the GenServer process in the test. Once the GenServer process exits a :DOWN message should be sent to the test process. The test can assert that the correct message was received.

    test "MyGenServer exits after an_action", fixtures do

# Start the GenServer
{:ok, pid} = start_supervised(MyGenServer)

# Monitor the GenServer process
ref = Process.monitor(pid)

# Start an action on the GenServer
MyGenServer.an_action(pid)

# Assert that the :DOWN message for the GenServer process was received
# I decided to allow the message to arrive in a timeframe 10 times bigger than the allowed inactive period is
# If the message isn't received by then the test is marked as failed
assert_receive {:DOWN, ^ref, :process, pid, :normal}, MyGenServer.allowed_inactive_period() * 10
end

This solution applies to any type of Elixir process, not only to GenServers.