0

我正在学习在 Elixir 中进行测试,并且出现了这个问题:

当我运行以下测试时,有时它通过,有时没有,我认为这是主管没有时间重新启动 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

发生时,这是错误:

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)

我该如何防止这种情况发生?超时是一个好方法吗?

4

2 回答 2

4

在没有竞争条件的情况下有效测试此行为的唯一方法是:

  1. 确保旧进程已死。这可以通过在发送终止信号之前监控进程来完成,然后assert_receive {:DOWN, ^monitor_ref, _, _, _}

  2. 查询主管,直到活动计数变为 1。这可以通过每 10ms 左右执行一次函数来完成

然而,正如其他人所说,这种行为是由 Erlang/OTP 保证的。因此,与其测试主管是否真的在重新启动某些东西,我宁愿测试您是否将正确的子规范传递给主管。因此,假设主管启动基于 的处理KV.Registered,我会这样做:

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

换句话说,我会测试与主管的合同,而不是测试主管本身。

于 2019-05-23T08:41:14.173 回答
2

这是一个时间问题。简短的版本是不要打扰测试 OTP。IT 已经经过了很好的测试。

但是,如果您将来有一个案例需要确保初创公司正常工作,了解主管如何启动服务器是有用的,请观看此视频 https://www.youtube.com/watch?v=2i_XrY5CCXE

于 2019-05-23T06:11:41.477 回答