Testing that a GenServer exited
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.