我正在使用 Mox 来模拟我的应用程序中的一些模块。通常,它工作正常,但我有一个在 FLAME.call/2 中调用的函数,它破坏了我的模拟:
** (Mox.UnexpectedCallError) no expectation defined for Zoonk.Storage.StorageAPIMock.optimize!/2 in process #PID<0.5593.0> with args ["16.png", 500]
(mox 1.1.0) lib/mox.ex:820: Mox.__dispatch__/4
(zoonk 0.1.0) lib/storage/storage_context.ex:177: Zoonk.Storage.optimize!/2
(flame 0.2.0) lib/flame/runner.ex:431: anonymous fn/3 in FLAME.Runner.remote_call/4
显然,我需要使用
Mox.allow/3
来允许其他进程共享期望。但我需要该进程的PID。我怎样才能找到它?
我尝试过:
GenServer.whereis(Zoonk.FLAME.ImageOptimization)
GenServer.whereis(FLAME.Pool)
GenServer.whereis(FLAME.Runner)
这些似乎都不起作用。
我知道我可以
:set_mox_global
。但是,我无法异步运行测试。所以,我宁愿找到一种方法来使用 Mox.allow/3
来代替。
有什么想法吗?
这是对
FLAME
内部结构的一次奇特的深入:)
FLAME.Pool
时,实际的 Mox.allow/3
跑步者尚未生成。如果您将文档读到最后,您会发现,mox
已准备好以 递延津贴 来处理此类情况
如果在定义配额时进程尚未启动,则假设在调用时它已启动,则可以将其作为函数允许。如果函数在调用期间无法解析为 pid,则期望将不会成功。
allow(MyMock, self(), fn -> GenServer.whereis(Deferred) end)
也就是说,
FLAME.call/2
委托给 FLAME.Pool
来启动受监控的任务。不幸的是,这个任务没有被命名,这意味着要达到它的pid
,我们需要一些进一步的调查。虽然它看起来有点老套,但坦率地说,我怀疑如果不深入研究内部结构,是否可以做到这一点。 FLAME
存储库中暴露任务 pid
的问题可能值得创建。
无论如何。
这里是从池中检索跑步者的
pid
的代码(带注释)。
MyApp.MyMod.Mox # the mox to allow expectations
|> allow(self(), fn ->
:sys.get_state(Zoonk.FLAME.ImageOptimization).callers # callers of Pool
|> Enum.flat_map(fn {pid, _} -> Process.info(pid)[:links] end) # backlinks
|> hd() # first one
end)
|> expect(:fun, fn … -> … end)