Python unittest模拟类和类方法

标签 python python-3.x unit-testing mocking python-unittest

我觉得这可能相对简单,但我正在竭尽全力让它发挥作用。我想模拟整个类,然后指定此类方法之一的返回值。

我已经看了here ,在其他几个问题上,当然在docs .我仍然无法让它工作。请看下面我的简单示例。

目录 tmp 的内容:

tmp
├── __init__.py
├── my_module.py
└── test_my_module.py

my_module.py 的内容:

class MyClass:
    def __init__(self):
        # Do expensive operations that will be mocked in testing.
        self.a = 7

    def my_method(self):
        # For sake of simple example, always return 1.
        return 1


def create_class_call_method():
    """Create MyClass instance and call its my_method method, returning
    the result."""
    instance = MyClass()
    value = instance.my_method()
    return value

test_my_module.py 的内容:

import unittest
from unittest.mock import patch, Mock

from tmp import my_module


class MyClassTestCase(unittest.TestCase):

    def test_create_class_call_method(self):
        # Attempt to patch MyClass as well as specify a return_value for
        # the my_method method (spoiler: this doesn't work)
        with patch('tmp.my_module.MyClass',
                   my_method=Mock(return_value=2)):
            value = my_module.create_class_call_method()

        self.assertEqual(value, 2)


if __name__ == '__main__':
    unittest.main()

运行 test_my_module.py 的结果:

2 != <MagicMock name='MyClass().my_method()' id='140234477124048'>

Expected :<MagicMock name='MyClass().my_method()' id='140234477124048'>
Actual   :2

我尝试过的其他一些事情:

  • 而不是 ..., my_method=Mock(return_value=2))patch 语句中,像这样解压字典:**{' my_method.return_value': 2}
  • 嵌套的 with patch 语句。外部语句很简单,如 with patch('tmp.my_module.MyClass'):,内部语句尝试修补 my_method,如下所示:with patch('tmp. my_module.MyClass.my_method, return_value=2)
  • 使用补丁装饰器代替上下文管理器
  • 将补丁语句更改为 with patch('tmp.my_module.MyClass') as p: 然后在 with 语句中,尝试设置 p 像这样:p.evaluate = Mock(return_value=2)

感谢任何帮助,谢谢。

最佳答案

我找到了一个更好的解决方案。简而言之,我们需要模拟 MyClass 模拟的 return_value。这是工作测试代码:

import unittest
from unittest.mock import patch, Mock, MagicMock

from tmp import my_module


class MyClassTestCase(unittest.TestCase):

    def test_create_class_call_method(self):
        # Create a mock to return for MyClass.
        m = MagicMock()
        # Patch my_method's return value.
        m.my_method = Mock(return_value=2)

        # Patch MyClass. Here, we could use autospec=True for more
        # complex classes.
        with patch('tmp.my_module.MyClass', return_value=m) as p:
            value = my_module.create_class_call_method()

        # Method should be called once.
        p.assert_called_once()
        # In the original my_method, we would get a return value of 1.
        # However, if we successfully patched it, we'll get a return
        # value of 2.
        self.assertEqual(value, 2)


if __name__ == '__main__':
    unittest.main()

以及成功的结果:

Ran 1 test in 0.002s

OK

关于Python unittest模拟类和类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57044593/

相关文章:

python - 如何判断程序是否打开

python - 使用字典键转换列表中的元素

java - 如何在 Java 单元测试中模拟接口(interface)?

python - 在终端中调用 "python3"时如何停止 Python 2.7 运行?

从不同文件导入类时,Python 3 是实例意外行为吗?

javascript - 我什么时候应该在我的 Angular JS 单元测试中使用 $provide 与 Jasmine Spies

c++ - Visual Studio 2017 native 单元测试 - 对项目的引用不起作用

python - 如何使用 Python 为不同的前缀同时运行 AWS S3 sync 命令

python - 杀死一个正在用正则表达式监听的端口

python - 计算内容的大小