如何解决每次测试后停止 GenServer
背景
我有一组测试需要之前启动 GenServer。根据经验,我知道每次测试后进行清理是一个很好的做法,所以我也想在每次测试后停止 GenServer。
问题
这里的问题是我不知道如何在测试完成后停止 GenServer。我总是遇到一些并发问题。
defmodule MyModuleTest do
use ExUnit.Case
alias MyModule
setup do
MyModule.Server.start_link(nil)
context_info = 1
more_info = 2
%{context_info: context_info,more_info: more_info}
end
describe "some tests" do
test "returns {:ok,order_id} if order was deleted correctly",context do
# do test here that uses created server and passed context
assert actual == expected
#clean up?
end
end
end
现在,我尝试了 on_exit
/2,如下所示:
setup do
{:ok,server} = MyModule.Server.start_link(nil)
context_info = 1
more_info = 2
on_exit(fn -> GenServer.stop(server) end)
%{context_info: context_info,more_info: more_info}
end
但我收到此错误:
** (exit) exited in: GenServer.stop(#PID<0.296.0>,:normal,:infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name,possibly because its application isn't started
我觉得这退出的太早了。
我也尝试使用 start_supervised
,但是因为我的 GenServer
在 handle_continue
中有一个冗长的初始化,测试在服务器准备好之前运行。
问题
我该如何解决这个问题?
解决方法
我终于弄清楚发生了什么。
结果 start_supervised
按预期工作,实际上 正在等待 GenServer 结束 handle_continue
(嗯,这不是完全等待,它仍然发送消息并将这些消息放入队列等待适当的时间执行)。
这里的问题是我没有对我在 handle_continue
中启动的所有内容进行全面清理。事实证明,即使在原始 GenServer 死掉之后,我启动的一些连接和进程仍然存在。
解决方案有两方面:
- 捕捉所有停止信号
- 一旦检测到停止信号,就正常关闭
在代码中,这被翻译成:
def init(_) do
Process.flag(:trap_exit,true) # trap all exits!
{:ok,%{},{:continue,:setup_queue}}
end
def handle_continue(:setup_queue,state) do
# do heavy lifting
{:noreply,state}
end
def terminate(_reason,state),do:
# undo heavy lifting
在我的 start_supervised
块中使用这个和 setup
,一切都很好。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。