使用unittest mock Redis调用失败,仍执行真实方法报错求助
解决unittest中Mock Redis Database不生效的问题
我来帮你分析下问题所在,以及如何正确Mock你的Redis调用:
问题根源
你的测试代码Mock没生效的核心原因有两个:
- 模块级实例化时机问题:在
app.py里,你在模块级别直接初始化了db = Database('zset')。当你的测试代码导入app模块时,这行代码就已经执行了,真实的Database实例已经被创建完成,后续在测试方法里的Mock根本影响不到这个已经存在的实例。 - 断言内容不匹配:你的测试断言写的是
'shivam word added.',但app.py里的add_word函数返回的是'{} added'.format(word),也就是实际返回是'shivam added',这个不一致也会导致测试失败。
解决方案
下面给你两种可行的修正方案:
方案一:在导入app模块前Mock Database类
这种方式可以确保app模块初始化时使用的就是Mock后的Database类:
import unittest import sys import os from unittest import mock # 先执行Mock,再导入app模块 with mock.patch('redis_db.Database') as mock_db_class: # 创建Mock的实例并设置预期行为 mock_db_instance = mock_db_class.return_value mock_db_instance.add.return_value = "" # 现在导入app,此时app里的db会是Mock的实例 sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../api/") from api import app # noqa: E402 class Testing(unittest.TestCase): def test_add_word(self): result = app.add_word('shivam') # 验证add方法是否被正确调用 mock_db_instance.add.assert_called_once_with('shivam') # 修正断言,和实际返回内容一致 self.assertEqual(result, 'shivam added')
方案二:直接Mock已实例化的db对象的add方法
既然app模块已经创建了db实例,我们可以直接Mock这个实例的add方法,跳过对类的Mock:
import unittest import sys import os from unittest import mock # 先导入app模块 sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../api/") from api import app # noqa: E402 class Testing(unittest.TestCase): def test_add_word(self): # Mock app.db的add方法 with mock.patch.object(app.db, 'add') as mock_add: result = app.add_word('shivam') # 验证add方法被调用的参数是否正确 mock_add.assert_called_once_with('shivam') # 修正断言内容 self.assertEqual(result, 'shivam added')
额外说明
- 两种方案里我都添加了
assert_called_once_with的验证,这能确保你的add方法确实被传入了正确的参数,让测试更严谨。 - 记得检查你的测试断言和实际返回值是否匹配,避免因为这个导致不必要的测试失败。
内容的提问来源于stack exchange,提问作者shivams
相关产品推荐
相关产品推荐

