Mateus Luiz
Mateus Luiz

Reputation: 796

In Elixir ExUnit, how do I guarantee that the Supervisor will create a new GeNserver?

I'm learning to test in Elixir and this problem appeared:

When I run the following test, sometimes it passes and sometimes don't, I'm thinking it is the fact that the Supervisor don't have the time to restart the GenServer:

  test "Supervisor will revive the dead gensever" do
    {:ok, pid} = KV.Supervisor.start_link([])
    KV.RegistryClient.create KV.RegistryClient, "wallet"
    [h | _] = Supervisor.which_children(pid)
    {KV.RegistryClient, pid_reg, _, _} = h
    send(pid_reg, :insta_kill)

    assert %{active: 1} = Supervisor.count_children(pid)
  end

When occurs, this is the error:

1) test Supervisor will revive the dead gensever (KV.RegistryTest)
     test/kv/registry_test.exs:35
     match (=) failed
     code:  assert %{active: 1} = Supervisor.count_children(pid)
     right: %{active: 0, specs: 1, supervisors: 0, workers: 1}
     stacktrace:
       test/kv/registry_test.exs:41: (test)

How do I prevent this to happen? A timeout is a good approach?

Upvotes: 0

Views: 567

Answers (2)

José Valim
José Valim

Reputation: 51349

The only way you can effectively test this behaviour without race conditions is by:

  1. Making sure the old process is dead. This can be done by monitoring the process before you send the kill signal and then assert_receive {:DOWN, ^monitor_ref, _, _, _}

  2. Query the supervisor until the active count changes to one. This can be done by executing a function once every 10ms or so

However, as others have said, this behaviour is guaranteed by Erlang/OTP. Therefore, instead of testing if a supervisor is actually restarting something, I would rather test if you are passing the proper child specification to the supervisor. So assuming the supervisor starts a processed based on KV.Registered, I would do this:

assert %{restart: :permanent} = Supervisor.child_spec(KV.Registered)

In other words, I would test the contract with supervisors, without testing the supervisors themselves.

Upvotes: 4

Zachary K
Zachary K

Reputation: 3335

It is a timing issue. The short version is don't bother testing OTP. IT is very well tested already.

But if you have a case in the future where you need to ensure startups work correctly understanding how Supervisors start servers is useful, see this video https://www.youtube.com/watch?v=2i_XrY5CCXE

Upvotes: 2

Related Questions