You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 16:57:37