Python Mock Patch未生效问题:为何仅第二个函数被Mock?
关于unittest.mock未正确Mock requests.Session的问题解析
问题现象
执行测试代码后,my_func中的Session未被Mock,而my_func2中的Session被成功Mock:
测试代码
import unittest from unittest.mock import patch, Mock import requests from requests import Session def my_func(): s = Session() print('my_func', type(s)) def my_func2(): s = requests.Session() print('my_func2', type(s)) class Test(unittest.TestCase): @patch("requests.Session", new=Mock) def test1(self, *args): my_func() @patch("requests.Session", new=Mock) def test2(self, *args): my_func2()
输出结果
my_func <class 'requests.sessions.Session'> my_func2 <class 'unittest.mock.Mock'>
原因分析
核心原因是unittest.mock.patch作用的是对象被引用的位置,而非定义位置:
my_func2直接调用requests.Session,patch("requests.Session")会替换requests模块内的Session引用,因此生效;my_func使用的是从requests导入到当前模块的Session,这个引用在导入阶段就绑定到了当前模块的命名空间,patch("requests.Session")修改的是requests模块内的对象,不会影响当前模块已导入的Session引用。
正确的Mock实现方式
有两种可行方案:
方案1:Patch当前模块的Session引用
针对当前模块中导入的Session进行patch(假设当前脚本为入口文件,用__main__.Session;若为命名模块,替换为模块名,比如my_module.Session):
import unittest from unittest.mock import patch, Mock import requests from requests import Session def my_func(): s = Session() print('my_func', type(s)) def my_func2(): s = requests.Session() print('my_func2', type(s)) class Test(unittest.TestCase): @patch("__main__.Session", new=Mock) def test1(self, *args): my_func() @patch("requests.Session", new=Mock) def test2(self, *args): my_func2()
方案2:统一函数内的引用方式
修改my_func,让它也使用requests.Session的调用方式,这样只需patchrequests.Session即可同时覆盖两个函数:
def my_func(): # 改用requests.Session()而非直接使用导入的Session s = requests.Session() print('my_func', type(s))
内容的提问来源于stack exchange,提问作者Philippe Remy
相关产品推荐
相关产品推荐

