I’ve used Process.flag(:trap_exit, true)
(Process.flag/2
) in the past inside the test module - just make sure to purge the resulting :EXIT
message from the test process mailbox.
Looking at catch_exit/1
it seems to be designed to catch an exit inside the same process that triggered it with Kernel.exit/1
Example: see test "FrequencySup demo"
defmodule FrequencySupTest do
use ExUnit.Case
setup do
{:ok, sup} = FrequencySup.start_link()
on_exit fn ->
refute (Process.alive? sup), "Supervisor still running!"
end
[sup: sup]
end
defp wait(_, _, left) when left < 1 do
nil
end
defp wait(fun, timeout, left) do
case fun.() do
nil ->
Process.sleep timeout
wait fun, timeout, (left - 1)
result ->
result
end
end
defp whereisFrequency,
do: Process.whereis Frequency
defp terminate_wait({pid, terminate}) do
ref = Process.monitor pid
terminate.()
receive do # wait for the supervisor to terminate
{:DOWN, ^ref, :process, _object, _reason} ->
Process.demonitor ref, [:flush]
end
end
test "FrequencySup demo", context do
sup = context[:sup]
Process.flag :trap_exit, true
initial_pid = whereisFrequency()
assert (Kernel.is_pid initial_pid)
fovl_pid = Process.whereis FreqOverload
assert (Kernel.is_pid fovl_pid)
# Kill off frequency
terminate_wait({initial_pid, (fn -> Process.exit initial_pid, :kill end)})
# Wait until replacement Frequency is up and running
freq_pid = wait &whereisFrequency/0, 10, 10
assert (Kernel.is_pid freq_pid)
# Use Supervisor.which_children/1
expected_children = Enum.sort [
{Frequency, freq_pid, :worker, [Frequency]},
{FreqOverload, fovl_pid, :supervisor, [FreqOverload]}
]
assert (expected_children == (Enum.sort (Supervisor.which_children sup)))
# Use Supervisor.count_children/1
expected_count = %{active: 2, specs: 2, supervisors: 1, workers: 1}
assert (Map.equal? expected_count, (Supervisor.count_children sup))
# Now stop the supervisor
terminate_wait({sup, &FrequencySup.stop/0})
assert_received {:EXIT, _, :shutdown}
Process.flag :trap_exit, false
end
end
I wasn’t writing a unit test as much as I was solidifying my understanding of the API.