Python单元测试中后续测试的Mock为何无法覆盖前置测试的Mock?
问题解决:批量运行Python单元测试时Mock失效
问题根源
你的main.py在模块加载阶段就创建了全局的s3实例:
# main.py s3 = boto3.client('s3') # 模块导入时执行
第一次测试导入src.main时,boto3.client已被Patch,生成的s3是第一个测试的Mock对象。由于Python模块是单例的,后续测试即使重启Patch,src.main不会重新加载,里面的s3始终是第一次的Mock,和你在setUp中创建的新self.mock_s3不是同一个对象,导致修改新Mock的返回值不生效。
修复方案
方案一:修改业务代码(推荐)
延迟s3实例的创建,让每次调用main()时都重新获取客户端,确保Patch能覆盖:
# main.py import boto3 def main(): s3 = boto3.client('s3') # 函数内部创建,每次调用都会执行 return s3.list_buckets()
方案二:不修改业务代码,在测试中刷新模块
在测试基类的setUp中重新加载src.main,强制模块级代码重新执行:
# test_base.py import unittest from unittest.mock import MagicMock, patch import importlib import src.main class TestBase(unittest.TestCase): def setUp(self): self.patch_boto3_client = patch('boto3.client', autospec=True) self.mock_boto3_client = self.patch_boto3_client.start() self.mock_s3 = MagicMock() self.mock_boto3_client.side_effect = lambda service: { 's3': self.mock_s3, }[service] # 重新加载main模块,让s3实例重新创建 importlib.reload(src.main) def tearDown(self) -> None: self.patch_boto3_client.stop()
验证效果
修改后重新运行测试:
$ python3 -m coverage run -m unittest test .. ---------------------------------------------------------------------- Ran 2 tests in 0.123s OK
内容的提问来源于stack exchange,提问作者Disciple153
相关产品推荐
相关产品推荐

