在Elixir Supervisor和Application教程中,为什么assert_receive会超时?

时间:2015-02-27 23:39:28

标签: elixir otp

在Elixir入门教程中,在关于Supervisors and Applications的页面上,有一个名为“在崩溃时移除存储桶”的测试。在页面上添加代码后(我想我添加了它,可能会遗漏一些东西),测试失败并在assert_receive中超时。

test "removes bucket on crash", %{registry: registry} do
    KV.Registry.create(registry, "shopping")
    {:ok, bucket} = KV.Registry.lookup(registry, "shopping")

    # Kill the bucket and wait for the notification
    Process.exit(bucket, :shutdown)
    assert_receive {:exit, "shopping", ^bucket}
    assert KV.Registry.lookup(registry, "shopping") == :error
end

这是输出:

$ mix test
....

1) test removes bucket on crash (KV.RegistryTest)
   test/kv/registry_test.exs:49
   No message matching {:exit, "shopping", ^bucket} after 100ms. Process mailbox:
   {:create, "shopping", #PID<0.137.0>}
   stacktrace:
     test/kv/registry_test.exs:55

Process.exit的帮助表示如果陷阱进程退出,则消息为{:EXIT,from,reason}。

跟踪这样的错误有什么好的策略?

1 个答案:

答案 0 :(得分:1)

我认为您的实施问题是in this line 您等待:DOWN消息,退出原因为:normal。如果存储区进程因任何其他原因而终止,则您将无法匹配此消息,并且它不会传播到GenEvent

:normal更改为_(以匹配流程退出的任何原因)修复了测试。

我得出的方法是,在理解了代码并且没有看到明显的错误之后,我添加了一些临时值。 IO.inspect在几个地方。我立即注意到注册表进程没有处理:DOWN消息。看到显示器设置正确,我怀疑消息的模式匹配方式有问题。盯着那条线几秒钟给了我答案: - )