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

如何使用pytest patch装饰器测试Ray Actor的远程函数

Ray 非本地模式下远程Actor方法打补丁失败的解决方案

问题原因

Ray 非本地模式运行时,所有 Actor 都会被调度到独立的 Worker 进程中执行,测试主进程通过 @patch 打的补丁仅作用于主进程内存空间,不会同步到远程 Worker 进程,因此远程 Actor 调用的还是原始方法,导致测试失败。本地模式下所有逻辑都在同一进程运行,所以补丁可以正常生效。

解决方案

以下两种方案都不需要开启local_mode即可生效:

方案1:Actor初始化时主动打补丁

在远程Actor实例化阶段,先在当前Worker进程执行补丁逻辑,适配单个测试用例的补丁需求:

# 测试文件新增:Worker进程执行的补丁逻辑
def patch_foo_bar():
    from unittest.mock import patch
    # 注意导入必须放在函数内部,保证Worker进程可以加载到对应模块
    from foo import Foo
    patcher = patch("foo.Foo.bar", new=fake_bar)
    patcher.start()

# 新增带补丁的Actor包装类
@ray.remote
class PatchedFoo(Foo):
    def __init__(self):
        # 实例化时先在当前Worker打补丁
        patch_foo_bar()
        super().__init__()

# 修改后的测试用例
def test_bar_remote(self):
    foo_actor = PatchedFoo.remote()
    obj_ref = foo_actor.bar.remote()
    ray.get(obj_ref)

方案2:全局Worker启动钩子批量打补丁

如果需要给所有测试用例的Worker都打上相同补丁,可以在Ray初始化时配置启动钩子,所有Worker进程启动后会自动执行补丁逻辑:

# 复用上面定义的patch_foo_bar函数
@pytest.fixture
def ray_fixture():
    print("Initializing ray")
    if not ray.is_initialized():
        ray.init(
            runtime_env={
                # 配置Worker进程启动钩子
                "worker_process_setup_hook": patch_foo_bar
            }
        )
    yield None
    print("Terminating ray")
    ray.shutdown()

配置后原有的test_bar_remote代码不需要任何修改即可正常运行。

注意事项

  • 所有需要在Worker进程执行的函数(补丁函数、fake方法等)都必须定义在模块顶层,保证Ray可以正常序列化和在Worker端导入
  • 补丁逻辑内的模块导入必须放在函数内部,避免主进程和Worker进程的导入路径不一致导致的报错

内容的提问来源于stack exchange,提问作者user1264641

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 00:54:01