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

如何在不Mock配置的情况下Mock链式导入的ActionHelpers.perform_action方法

问题

我有一个供开发者按需修改的常量配置文件,为提升可读性拆分结构如下:

from app.configuration.foo.main import FOO_RULES

MAIN_RULES = {
  'foo': FOO_RULES
}

FOO_RULES的定义如下:

from app.helpers.foo.action_helpers import ActionHelpers

FOO_RULES = {
  'bar': {
     'action_func': ActionHelpers.perform_action,
   },
}

另有RuleRunner类导入MAIN_RULES,调用时动态解析配置,若action_func不为None则传入固定参数调用:

from app.configuration.main import MAIN_RULES

class RuleRunner:
  def __init__(self, rule_book):
     self.__rule_book = MAIN_RULES

  def run_rule(self, rule, val_1, val_2):
    rule = self.__rule_book[rule]
    action_func = rule['action_func']

    if action_func is not None:
      action_func(val_1, val_2)

由于配置是应用核心部分需测试,但我不想Mock MAIN_RULES(避免重复测试常量),却需Mock ActionHelpers.perform_action(该方法已有单独单元测试)。现寻求如何在不Mock整个配置的前提下,正确Mock这个链式导入的方法,测试代码中??????处应填写什么模块路径:

from app.runners import RuleRunner
import mock

@mock.patch('??????.ActionHelpers.perform_action')
def test_run_role_foo_bar_rule(action_helper_perform_action):
  val_1 = 'fizz'
  val_2 = 'buzz'

  RuleRunner('foo').run_rule('bar', val_1, val_2)

  action_helper_perform_action.assert_called_with(val_1, val_2)
解决方案

你需要填写的模块路径是**app.configuration.foo.main**。

原因很明确:ActionHelpers.perform_action是在app.configuration.foo.main模块中被导入,并且被赋值给FOO_RULES['bar']['action_func']的。当MAIN_RULES导入FOO_RULES后,实际引用的是该配置模块中已经绑定的函数对象。要Mock这个被配置引用的函数实例,必须针对它被绑定的模块路径进行操作,而非原函数所在的模块。

修改后的测试代码如下:

from app.runners import RuleRunner
import mock

@mock.patch('app.configuration.foo.main.ActionHelpers.perform_action')
def test_run_role_foo_bar_rule(action_helper_perform_action):
  val_1 = 'fizz'
  val_2 = 'buzz'

  RuleRunner('foo').run_rule('bar', val_1, val_2)

  action_helper_perform_action.assert_called_with(val_1, val_2)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 12:35:31