首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Python单元测试模拟类和类方法

Python单元测试模拟类和类方法
EN

Stack Overflow用户
提问于 2019-07-16 01:29:00
回答 2查看 6.5K关注 0票数 6

我觉得这可能是相对简单的,但我正在努力让它工作。我想模拟整个类,然后为该类的一个方法指定返回值。

我已经研究了here,还有其他几个问题,当然也是在docs中。我还是不能让它工作。请看下面我的简单示例。

目录tmp的内容

代码语言:javascript
复制
tmp
├── __init__.py
├── my_module.py
└── test_my_module.py

my_module.py的内容

代码语言:javascript
复制
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的内容

代码语言:javascript
复制
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的结果

代码语言:javascript
复制
2 != <MagicMock name='MyClass().my_method()' id='140234477124048'>

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

我还尝试过其他一些方法:

使用**{'my_method.return_value': 2}

  • Nested

  • 语句而不是patch语句中的..., my_method=Mock(return_value=2))来解压缩字典。外部语句像with patch('tmp.my_module.MyClass'):一样简单,内部语句尝试像这样修补my_methodp.evaluate = Mock(return_value=2)

将修饰器而不是上下文with patch('tmp.my_module.MyClass'):语句修补为my_method,然后在with语句内部,尝试像这样设置p

感谢您的帮助,谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-07-25 00:18:54

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

代码语言:javascript
复制
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()

成功的结果是:

代码语言:javascript
复制
Ran 1 test in 0.002s

OK
票数 5
EN

Stack Overflow用户

发布于 2019-07-16 01:35:08

我不确定create_class_call_method的实现,但可以尝试以下方法:

代码语言:javascript
复制
from unittest import mock

class MyClassTestCase(unittest.TestCase):
    @mock.patch('tmp.my_module.MyClass.my_method')
    @mock.patch('tmp.my_module.MyClass.__init__')
    def test_create_class_call_method(self, my_class_init, my_method_mock):
        my_class_init.return_value = None
        my_method.return_value = 2

        value = my_module.create_class_call_method()

        self.assertEqual(value, 2)
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57044593

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档