Python unittest中使用mock替换randint不生效的问题如何解决?
问题原因
你的代码存在三个核心问题导致mock不生效/运行报错:
- 测试类的类属性
NUMBER在测试类加载阶段就完成了Calculator实例初始化,此时测试方法的@mock.patch装饰器还未生效,Calculator.__init__中调用的randint是官方库的真实方法,self.number2已经被赋值为真实随机值,后续测试执行时再mock已经不会影响已经生成的属性值。 - 不符合mock的「在哪里使用,就mock哪里」原则:你的代码通过
from random import randint把randint导入到了当前模块的命名空间,直接mockrandom.randint不会修改当前模块已经导入的randint引用,mock无法作用到Calculator的逻辑中。 @mock.patch装饰的测试方法会自动把mock对象作为入参传入,你的代码没有定义对应的形参会直接触发运行报错。
修复方案
调整初始化时机和mock路径即可,修改后可正常运行的代码如下:
from random import randint import unittest from unittest import mock class Calculator: def __init__(self, number): self.number = number self.number2 = randint(1, 5) def multi(self): return self.number * self.number2 class CalculatorTest(unittest.TestCase): # 用__name__动态获取当前模块名,mock当前模块命名空间下的randint @mock.patch(f'{__name__}.randint', return_value=4) def test_multi(self, mock_randint): # mock生效后再初始化Calculator,此时__init__调用的是mock后的randint test_calculator = Calculator(3) actual_result = test_calculator.multi() expected_result = 12 self.assertEqual(actual_result, expected_result, f'Actual result {actual_result}, expected {expected_result}') if __name__ == '__main__': unittest.main()
如果后续你把Calculator类拆分到了单独的calculator.py模块,只需要把mock路径修改为@mock.patch('calculator.randint', return_value=4)即可。
内容的提问来源于stack exchange,提问作者Dzmitry
相关产品推荐
相关产品推荐

