【问题标题】:How to test that a Phoenix socket is terminated?如何测试 Phoenix 套接字是否已终止?
【发布时间】:2017-03-03 10:26:51
【问题描述】:

我正在寻找一种方法来测试套接字是否被终止。被测代码是这样做的:

def handle_in("logout", _payload, socket) do
  {:stop, :logout, socket |> assign(:user, nil)}
end

而我的测试代码(改编自 http://elixir-lang.org/getting-started/try-catch-and-rescue.html#exits)是这样做的:

test "logout terminates the socket", %{socket: socket} do
  try do
    push socket, "logout"
  catch
    huh -> IO.puts("Caught something #{IO.inspect huh}")
    :exit, what -> IO.puts("Caught :exit #{IO.inspect what}")
  end
  assert_receive {:DOWN, monitor_ref, _, :normal}
end

但是当我运行测试时,我得到了这个:

1) test logout without login terminates the socket (Main.AuthChannelTest)
   test/channels/auth_channel_test.exs:47
   ** (EXIT from #PID<0.505.0>) :logout

.....09:06:41.139 [error] GenServer #PID<0.507.0> terminating
** (stop) :logout

我应该如何测试套接字关闭?

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    当你监控的进程宕机时发送的消息是{:DOWN, ref, :process, pid, reason},所以

    1. assert_receive 中应该有一个 5 元组

    2. 如果您想与原因 :normal 匹配,您应该以原因 :normal 终止。如果您这样做,您将不必捕捉任何退出信号(如果您确实想使用:logout 退出,请参见下文)。

    以下对我有用:

    def handle_in("logout", _payload, socket) do
      {:stop, :normal, socket |> assign(:user, nil)}
    end
    
    test "...", %{socket: %{channel_pid: channel_pid} = socket} do
      monitor_ref = Process.monitor(channel_pid)
      push socket, "logout", %{}
      assert_receive {:DOWN, ^monitor_ref, _, _, :normal}
    end
    

    如果您出于某种原因确实想要以:logout 的原因退出套接字,您还必须捕获退出,因为:normal 以外的任何原因都会导致退出信号发送到链接到一个进程的所有进程,并且在测试中,运行测试的进程链接到socket.channel_pid。以下作品:

    def handle_in("logout", _payload, socket) do
      {:stop, :logout, socket |> assign(:user, nil)}
    end
    
    test "...", %{socket: %{channel_pid: channel_pid} = socket} do
      Process.flag(:trap_exit, true)
      monitor_ref = Process.monitor(channel_pid)
      push socket, "logout", %{}
      assert_receive {:DOWN, ^monitor_ref, _, _, :logout} 
    end
    

    【讨论】:

    • 好的,谢谢。我已经决定 :normal 是一个充分的理由,所以我想我现在已经准备好了。
    【解决方案2】:

    通过 Elixir Slack 频道收到了很好的回答:

    修改测试代码以捕获退出信号。这是按预期工作的更新测试:

    test "logout terminates the socket", %{socket: socket} do
      Process.flag(:trap_exit, true)
      push socket, "logout"
      socket_pid = socket.channel_pid
      assert_receive {:EXIT, ^socket_pid, :logout}
    end
    

    请注意,这仍然存在控制台日志噪音,因此我已将退出原因更改为 :normal,一切都安静了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-22
      • 2020-06-03
      • 2010-11-29
      相关资源
      最近更新 更多