Controlling the Life Cycle of OTP Processes in Tests

Get introduced to a tool in ExUnit’s toolbox to help start and stop GenServers in our tests.

Why do we need to control the life cycle?

Until now, when we needed to start a GenServer in our tests, we always called the GenServer’s start_link/1 function directly. We even went as far as to have assertions on the return value of this function.

assert {:ok, pid} = RollingAverageServer.start_link(max_measurements: n)

This kind of assertion might be helpful to test that the start_link/1 function behaves correctly, but it has a critical drawback. The process that we start is tied to the life cycle of the test process but not in a clean way. The processes are just linked.

When the test finishes executing, the test process will terminate, and since our GenServer process is linked to it, the GenServer will terminate too. However, the test process doesn’t know that it has to wait for the process we started with start_link/1 to properly shut down. In other words, the GenServer process we start could still be shutting down when the next test starts, potentially leading to some nasty bugs and race conditions.

Get hands-on with 1200+ tech skills courses.