在我的应用程序中,我有一个 GenServer。它备份在代理中重新启动所需的数据。我想测试我的 GenServer 是否正确备份和恢复,所以我想启动备份代理,然后重新启动 GenServer 并查看它是否有效(记住重新启动之前的配置)。
现在我已经start_supervised!
在测试设置中配置并启动了 GenServer(使用 )。我需要以某种方式重新启动该 GenServer。
有什么好的方法吗?我应该完全不同吗?是否有不同的、正确的测试重启行为的方法?
在我的应用程序中,我有一个 GenServer。它备份在代理中重新启动所需的数据。我想测试我的 GenServer 是否正确备份和恢复,所以我想启动备份代理,然后重新启动 GenServer 并查看它是否有效(记住重新启动之前的配置)。
现在我已经start_supervised!
在测试设置中配置并启动了 GenServer(使用 )。我需要以某种方式重新启动该 GenServer。
有什么好的方法吗?我应该完全不同吗?是否有不同的、正确的测试重启行为的方法?
child_spec
主管决定何时通过该子进程的 重新启动其监督下的进程。默认情况下,当您定义 GenServer 模块并use GenServer
在模块上使用时,默认(重新启动值)将为:permanent
,这意味着如果退出,则始终重新启动此进程。
鉴于此,向它发送一个退出信号就足够了Process.exit(your_gen_server_pid, :kill)
(:kill
将确保即使进程正在捕获退出它也会被杀死),然后主管应该再次启动该进程,然后您可以进行断言。
您需要一种方法来解决“新” genserver 进程,因为它将被杀死,重新启动时它pid
不会与原来的相同,通常您通过在启动它时提供一个名称来做到这一点。
如果您的 genserver 将状态作为其一部分加载,init
您不一定需要监督它来测试备份行为,您可以单独启动它,杀死它,然后重新启动它。
取决于您如何建立备份等,可能存在边缘情况,但通常这就足够了。
更新:
要解决进程退出和重新启动的问题,您可以编写 2 个辅助函数来专门处理该问题。
def ensure_exited(pid, timeout \\ 1_000) do
true = Process.alive?(pid)
ref = Process.monitor(pid)
Process.exit(pid, :kill)
receive do
{:DOWN, ^ref, :process, ^pid, _reason} -> :ok
after
timeout -> :timeout
end
end
您可以改为使用 aname
和 doGenServer.whereis
来检索 pid,但想法是一样的。
为了确保它还活着:
def is_back_up?(name, max \\ 200, tries \\ 0) when tries <= max do
case GenServer.whereis(name) do
nil ->
Process.sleep(5)
is_back_up?(name, max, tries + 1)
pid -> true
end
end
def is_back_up?(_, _, _), do: false
基本思想是这样的。不确定是否已经有一些帮手来做这种事情。
然后您只需使用它(您可以编写第三个助手,它采用实时 pid、名称,并在一个“步骤”中完成所有操作),或编写:
:ok = ensure_exited(pid)
true = is_back_up?(name)