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

Python中如何mock非实例方法?实例方法mock正常非实例方法失效如何解决

问题解决:Python unittest mock非实例方法不生效的修复方案

根因分析

你在测试模块头部通过from common.send_mail import send_mail_2的方式直接导入了目标函数,导入操作会在测试模块的作用域内创建一个send_mail_2的变量,直接绑定到原始函数的内存地址。你当前的patch操作修改的是common.send_mail模块下的send_mail_2变量指向,不会影响测试模块内已经完成绑定的函数引用,因此mock不会生效。
而实例方法的mock能生效是因为你每次调用都是先实例化Email类,走的是common.send_mail模块下的类定义,因此patch原模块的类方法可以命中。

修复方案

提供两种可行的修改方式,任选其一即可:

方案1:修改patch路径,指向测试模块内导入的函数

直接patch测试模块作用域内已经导入的send_mail_2变量,替换后调用时就会走mock逻辑,修改后的测试代码如下:

import unittest
from unittest.mock import patch
from common.send_mail import Email, send_mail_2

class Test(unittest.TestCase):
    # 此处改为patch当前测试模块内的send_mail_2引用
    @patch('common.test_mocking.send_mail_2')
    @patch('common.send_mail.Email.send_mail')
    def test_send_email(self, mock_instance, mock_non_instance):
        mock_instance.return_value = 1
        mock_non_instance.return_value = 1
        res = Email().send_mail()
        assert res == 1
        res1 = send_mail_2()
        assert res1 == 1

方案2:调整导入和调用方式,通过模块访问目标函数

不单独导入send_mail_2,改为导入整个send_mail模块,调用时通过模块名访问函数,此时patch原模块的函数即可生效:

import unittest
from unittest.mock import patch
from common import send_mail # 导入整个模块,不单独导入函数

class Test(unittest.TestCase):
    @patch('common.send_mail.send_mail_2')
    @patch('common.send_mail.Email.send_mail')
    def test_send_email(self, mock_instance, mock_non_instance):
        mock_instance.return_value = 1
        mock_non_instance.return_value = 1
        res = send_mail.Email().send_mail()
        assert res == 1
        res1 = send_mail.send_mail_2() # 通过模块调用函数
        assert res1 == 1

注意事项

unittest的patch装饰器参数顺序和函数接收的mock参数顺序相反:越靠近测试函数的patch装饰器,对应的mock参数越靠前,你当前代码的参数顺序是正确的,无需调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:27:02