【问题标题】:Configure channel test timeout phoenix配置通道测试超时phoenix
【发布时间】:2018-04-02 06:53:37
【问题描述】:

我有一个通道,用于在执行某种同步时将消息推送到客户端:

defmodule AppWeb.SyncChannel do
  use AppWeb, :channel

  def join("sync:database", _payload, socket) do
    send(self(), {:sync, :database})

    {:ok, socket}
  end

  def handle_info({:sync, :database}, socket) do
    Process.sleep(2000)
    push(socket, "one", %{})
    Process.sleep(2000)
    push(socket, "two", %{})
    Process.sleep(2000)
    push(socket, "three", %{})

    {:noreply, socket}
  end
end

我对此频道进行了测试:

defmodule AppWeb.SyncChannelTest do
  use AppWeb.ChannelCase, async: false

  alias AppWeb.SyncChannel

  describe "sync:database" do
    setup do
      {:ok, _, socket} = subscribe_and_join(socket(), SyncChannel, "sync:database")

      {:ok, socket: socket}
    end

    test "socket pushes 3 messages", %{socket: _socket} do
      assert_push("one", %{})
      assert_push("two", %{})
      assert_push("three", %{})
    end
  end
end

但是当我运行测试时,我得到了错误:

Compiling 1 file (.ex)
...

  1) test sync:database socket pushes 3 messages (AppWeb.SyncChannelTest)
     test/app_web/channels/sync_channel_test.exs:13
     ** (exit) exited in: GenServer.call(#PID<0.478.0>, :socket, 5000)
         ** (EXIT) time out
     stacktrace:
       (elixir) lib/gen_server.ex:830: GenServer.call/3
       (phoenix) lib/phoenix/test/channel_test.ex:360: Phoenix.ChannelTest.join/4
       test/app_web/channels/sync_channel_test.exs:8: AppWeb.SyncChannelTest.__ex_unit_setup_1/1
       test/app_web/channels/sync_channel_test.exs:1: AppWeb.SyncChannelTest.__ex_unit__/2

.

Finished in 5.2 seconds
5 tests, 1 failure

Randomized with seed 119011

如何在我的测试中配置通道超时,以便handle_info 函数能够运行超过默认的 5 秒。

我曾尝试在config/ 文件中进行配置,但并不高兴,也可以在app_web/channels/user_socket.ex 中进行配置,但我再次找不到任何指定timeout 的地方

【问题讨论】:

  • 你能用stacktrace发布完整的错误信息吗?
  • 添加了堆栈跟踪,我可以创建一个简单的 github 存储库来复制问题,如果这样可以让事情变得更容易
  • 嗯,在 lib/phoenix/test/channel_test.ex:360 有一个 GenServer 调用,没有可配置的超时。您可以尝试将send(self(), {:sync, :database}) 更改为Process.send_after(self(), {:sync, :database}, 100)。不是真正的解决方案,但可能会奏效。
  • 进行更改后,我得到:1) test sync:database socket pushes 3 messages (AppWeb.SyncChannelTest) test/app_web/channels/sync_channel_test.exs:13 No message matching %Phoenix.Socket.Message{event: "one", payload: %{}} after 100ms. The process mailbox is empty. code: assert_push("one", %{}) stacktrace: test/app_web/channels/sync_channel_test.exs:14: (test) . Finished in 0.5 seconds 5 tests, 1 failure Randomized with seed 282816
  • 是的,您还需要增加 assert_push 的超时时间,因为默认情况下它只等待 100 毫秒,而您的消息会在 2 4 和 6 秒后出现:assert_push(..., ..., 10000)

标签: sockets testing timeout elixir phoenix-framework


【解决方案1】:

Phoenix.ChannelTest.join calls Phoenix.Channel.Server.socket/1 which makes a GenServer call to the channel with no configurable timeout 从 GenServer 的状态中获取底层套接字。我相信,由于您从 join 函数向 self 发送消息,因此该消息在测试代码能够获取套接字值之前由 GenServer 处理,并且由于该调用的默认超时为 5 秒,因此您将获得此超时错误。

对此的解决方法是使用Process.send_after/3send 稍微延迟到self

Process.send_after(self(), {:sync, :database}, 100)

您还需要增加assert_push 调用的超时时间,因为超时默认为 100 毫秒,而您的消息在大约 6 秒后到达。

assert_push ..., ..., 10000

同样,Process.send_after/3 只是一种解决方法。更有知识的人可能能够提供真正的解决方案。

【讨论】:

    猜你喜欢
    • 2018-03-31
    • 1970-01-01
    • 2018-10-04
    • 2021-05-15
    • 1970-01-01
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多