如何从FLAME.call/2获取PID以解决Mox跨进程Mock失效问题
FLAME.call/2中Mox Mock失效的解决方案
问题背景
使用Mox模拟Zoonk.Storage.StorageAPIMock模块时,常规调用正常,但通过FLAME.call/2执行函数时Mock失效,报错如下:
** (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让其他进程共享预期,但FLAME动态创建的进程PID无法提前通过GenServer.whereis获取,且不想使用:set_mox_global(会破坏测试异步性)。
解决方案
1. 在FLAME任务内部主动授权
将测试进程的PID传递到FLAME任务中,在任务执行前调用Mox.allow/3,让FLAME进程获得使用测试进程Mox预期的权限:
test "通过FLAME调用图片优化接口" do test_pid = self() FLAME.call(MyFlamePool, fn -> Mox.allow(Zoonk.Storage.StorageAPIMock, test_pid, self()) Zoonk.Storage.optimize!("16.png", 500) end) end
2. 封装FLAME调用工具函数
为避免重复编写授权逻辑,封装一个通用的FLAME调用函数,自动处理Mox权限传递:
defmodule TestHelpers.FLAME do @doc "带Mox权限的FLAME调用" def call(pool, fun) do test_pid = self() FLAME.call(pool, fn -> Mox.allow(Zoonk.Storage.StorageAPIMock, test_pid, self()) fun.() end) end end # 测试代码中使用 test "优化图片" do TestHelpers.FLAME.call(MyFlamePool, fn -> Zoonk.Storage.optimize!("16.png", 500) end) end
3. 利用FLAME初始化钩子授权
如果使用FLAME的start_child等方式启动进程,可以在初始化回调中注入Mox授权逻辑:
test "启动FLAME子进程并执行任务" do test_pid = self() FLAME.start_child(MyFlamePool, %{test_pid: test_pid}, fn state -> Mox.allow(Zoonk.Storage.StorageAPIMock, state.test_pid, self()) # 执行具体任务逻辑 Zoonk.Storage.optimize!("16.png", 500) end) end
关键说明
FLAME的任务进程是动态创建的,执行时才生成PID,因此无法提前通过GenServer.whereis等方式获取。必须将测试进程的PID传递到任务内部,在进程启动后立即完成Mox授权,才能让Mock预期生效,同时保持测试的异步性。
内容的提问来源于stack exchange,提问作者Will
相关产品推荐
相关产品推荐

