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

求助:Django单元测试中mock.patch对顶部导入函数失效

问题:Django单元测试中mock.patch对顶部导入的外部函数失效

我有一个对接外部服务的Django应用,编写单元测试时需要用mock.patch打桩调用外部服务的函数,但顶部导入外部函数时patch无法生效,只有把导入放到方法内部才正常。

代码示例:

原api_views.py(patch失效)

#api_views.py
from examplemodule import examplefunction

class GetSomeInfoFromExternalService(ApiView):
   def get(self, *args, **kwargs):
       if examplefunction(attrs) == somevalue:
           return Response({'detail':'OK'})
       return Response({'detail':'Not ok'})

原tests.py

#tests.py
from unittest import mock  # 注:原代码拼写错误,应为unittest而非unittests,pach应为patch
from django.test import TestCase

class MyTestCase(TestCase):
    @mock.patch('examplemodule.examplefunction')
    def test_1(self, mock_func):
        mock_func.return_value=123
        # 此处需补充执行请求测试的代码

修改后可正常工作的api_views.py

#api_views.py
class GetSomeInfoFromExternalService(ApiView):
   def get(self, *args, **kwargs):
       from examplemodule import examplefunction
       if examplefunction(attrs) == somevalue:
           return Response({'detail':'OK'})
       return Response({'detail':'Not ok'})

请问该如何解决顶部导入时mock.patch失效的问题?


解决方案

核心原因

mock.patch的作用是替换目标模块中引用的对象,而非原模块里的原始对象。当你在api_views.py顶部导入examplefunction时,api_views模块会直接持有原函数的引用。此时你patchexamplemodule.examplefunction,只会修改原模块的引用,不会影响api_views里已经加载好的那个函数引用。

正确做法:patch目标模块中的引用路径

把patch的目标路径改成api_views.examplefunction,也就是api_views模块中实际使用的那个函数引用,而非原模块的路径。

修正后的tests.py代码:

#tests.py
from unittest import mock
from django.test import TestCase
from django.urls import reverse
from rest_framework.test import APIClient

class MyTestCase(TestCase):
    def setUp(self):
        self.client = APIClient()

    @mock.patch('api_views.examplefunction')  # 改为api_views中的引用路径
    def test_1(self, mock_example_func):
        # 设置mock返回值
        mock_example_func.return_value = 123
        
        # 发起请求测试
        url = reverse('your-api-url-name')  # 替换为你的API路由名称
        response = self.client.get(url)
        
        # 断言结果
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.data['detail'], 'OK')

额外注意事项

  1. 原代码里的from unittests import mock是拼写错误,正确应为from unittest import mock
  2. mock.pach是拼写错误,正确应为mock.patch
  3. 测试方法需要接收mock对象作为参数(如上述代码中的mock_example_func),才能设置返回值
  4. 测试中需实际发起API请求,才能触发mock的调用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:10:28