python - 使用装饰器补丁在 Python 中模拟类

标签 python python-unittest python-unittest.mock

我想在单元测试中修补 Python 中的一个类。主要代码是这样的(mymath.py):

class MyMath:
    def my_add(self, a, b):
        return a + b

def add_three_and_two():
    my_math = MyMath()
    return my_math.my_add(3, 2)

测试类是这样的:

import unittest
from unittest.mock import patch
import mymath

class TestMyMath(unittest.TestCase):
    @patch('mymath.MyMath')
    def test_add_three_and_two(self, mymath_mock):
        mymath_mock.my_add.return_value = 5

        result = mymath.add_three_and_two()

        mymath_mock.my_add.assert_called_once_with(3, 2)
        self.assertEqual(5, result)

unittest.main()

我收到以下错误:

AssertionError: Expected 'my_add' to be called once. Called 0 times.

最后一个断言也会失败:

AssertionError: 5 != <MagicMock name='MyMath().my_add()' id='3006283127328'>

我希望上述测试能够通过。我做错了什么?

更新: 限制:

  • 如果可能的话我不会改变测试过的部分。 (我很好奇这是否可能,这就是问题的重点。)
  • 如果不可能,那么我希望待测试部分的更改量最小。特别是我想让 my_add() 函数保持非静态。

最佳答案

无需修补整个类,只需修补函数即可。

class TestMyMath(unittest.TestCase):
    @patch.object(mymath.MyMath, 'my_add')
    def test_add_three_and_two(self, m):
        m.return_value = 5

        result = mymath.add_three_and_two()

        m.assert_called_once_with(3, 2)
        self.assertEqual(5, result)

我认为最初的问题是 my_math.my_add 每次使用时都会生成一个模拟对象;您配置了一个 Mockreturn_value 属性,但随后检查是否调用了另一个 Mock 实例。至少,使用 patch.object 可确保您尽可能少地干扰原始代码。

关于python - 使用装饰器补丁在 Python 中模拟类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74525368/

相关文章:

python - 如何使用 moto @mock_dynamodb2 模拟失败的操作?

python - Django导入错误: No module named allauth.

python - tensorflow 占位符形状 [None] [None,1] 区别

python - 如何在循环中运行多个 Python 测试用例?

python - 如何模拟List类型的全局变量?

Python 单元测试 : Test whether two angles are almost equal

Python单元测试.mock : patched class method called but assertion fails

python - 计算大矩阵 (300000 x 70000) 的均值和协方差

python - 为 Distutils list 模板使用 MANIFEST.in 以外的名称

python - 如何在python中对数据库连接pymysql进行单元测试?