在 init_per_suite 中创建的命名 gen_server 进程在测试中不存在

Posted

技术标签:

【中文标题】在 init_per_suite 中创建的命名 gen_server 进程在测试中不存在【英文标题】:Named gen_server process created in init_per_suite is not present in tests 【发布时间】:2021-03-13 19:45:08 【问题描述】:

我正在学习 erlang,我创建了一个实现 gen_server behaviourcache_server 模块。

该模块负责创建ets tables,并有一个api用于插入、查找等

我想为模块制作测试套件,并在一组测试中按顺序运行测试用例以进行插入和查找,因为第一个函数填充表和其他搜索插入的键。

我尝试在套件的 init_per_suite 钩子函数中调用 cache_server:start_link([]),但在测试用例中,当我调用 registered() 函数时,我看不到我的 cache_server 进程。

我得到了

noproc,gen_server,call,[cache_server,lookup,numbers,1]

错误。

我还尝试将调用 cache_server:start_link() 从 init_per_suite 移动到第一个测试用例,但在随后的测试用例中,该过程变得不可用。

当我使用 rebar3 shell 手动测试我的代码时,一切都按预期工作。

是否可以在通用测试套件中的测试用例之间共享一个命名的 gen_server 进程?

【问题讨论】:

您是否尝试过使用 gen_server:start(...) 而不是 gen_server:start_link(...) 来启动服务器? (即不要将其链接到评估 init_per_suite/1 的过程) 嗨,布鲁霍!感谢您的回复,不,我没有尝试这样做。我调用 cache_server:start_link() ,它的定义如下:start_link(Opts) -> gen_server:start_link(local, ?MODULE, ?MODULE, Opts, [])。调用 gen_server:start 而不是 gen_server:start_link() 有什么区别? 顺便说一句,如果我调用cache_server:start_link([]),将数据插入表并在一个测试用例中一起查找数据,它通过了。但我想按模块功能将其拆分为测试用例。我已经阅读了通用测试库文档,特别是不建议创建依赖测试用例,但就我而言,它们本质上是如此紧密依赖。 start_link 将启动的进程与当前进程链接,而 start 则没有。更多信息:learnyousomeerlang.com/errors-and-processes 谢谢,布鲁霍!那行得通,我在 init_per_suite 函数中将 cache_server:start_link([drop_interval, 10]) 更改为 gen_server:start(local, cache_server, cache_server, [drop_interval, 10], []) 并且我的服务器进程保持不变活着,测试用例通过了!请添加答案让我接受。 【参考方案1】:

尝试在init_per_testcase 中调用cache_server:start_link()。由于此函数在每个测试用例之前执行,因此您还需要停止 end_per_testcase 中的 cache_server 进程。

另一种选择是将所有cache_server相关的测试用例分组在一个组中,并在init_per_group中调用cache_server:start_link()并在end_per_group中停止进程

【讨论】:

谢谢,但是我的测试用例是分组的,并且该组具有 [sequence] 属性,我已经尝试在 init_per_group 中调用 cache_server:start_link(),它没有帮助。 如果您已将您的代码结构化为 OTP 应用程序(命名为 cache_server),然后在 init_per_suite 中尝试 application:ensure_all_started(cache_server),然后在 init_per_suite 中调用 cache_server:start_link() 感谢您的帮助,这可能有效,但我想在不启动整个应用程序的情况下测试我的模块。我已经从 cmets 的 Brujo 那里得到了我的问题的工作解决方案:我需要调用 gen_server:start(local, cache_server, cache_server, [drop_interval , 10], []) 在 init_per_suite 中。这个技巧有效,因为以这种方式启动的服务器进程没有链接到调用进程,显然新进程是为每个测试用例生成的,包括 init_per_suite 准备

以上是关于在 init_per_suite 中创建的命名 gen_server 进程在测试中不存在的主要内容,如果未能解决你的问题,请参考以下文章

释放在 WPF Application.OnStartUp() 中创建的命名互斥锁:哪个线程拥有它?

使用对象属性的 JPA 命名查询

Django Annotate - 我可以将在 annotate 中创建的字段用于在 annotate 中创建的另一个字段吗?

Tcl学习之--命名空间

Tcl学习之--命名空间

如何模拟在函数中创建的类(新运算符)?