我有一个频道,用于在执行某种同步时将消息推送到客户端:
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
答案 0 :(得分:1)
Phoenix.ChannelTest.join
calls Phoenix.Channel.Server.socket/1
makes a GenServer call to the channel with no configurable timeout从GenServer的状态获取底层套接字。我相信,既然您从join
函数向自己发送消息,那么在测试代码能够获取套接字值之前,GenServer会处理该消息,并且由于该调用的默认超时为5秒,因此这个超时错误。
解决方法,使用send
将self
略微推迟到Process.send_after/3
:
Process.send_after(self(), {:sync, :database}, 100)
您还需要增加assert_push
来电的超时时间,因为超时默认为100毫秒,而您的消息则会在6秒后到达。
assert_push ..., ..., 10000
同样,Process.send_after/3
只是一种解决方法。知识渊博的人可能能够提供真正的解决方案。