【问题标题】:Unable to Use pytest-mock in pytest to Verify Construction and Instance Method Calls Simultaneously无法在pytest中使用pytest-mock同时验证构造和实例方法调用
【发布时间】:2017-06-24 21:45:17
【问题描述】:

首先,我使用 pytest-mock 和 pytest 包来测试我正在开发的软件项目。

我有一种情况,我正在测试模块中的一个类,并试图模拟一个复合对象,它从其__init__ 方法实例化。当我这样做时,我能够断言 __init__ 方法被正确调用,但是当我尝试断言实例方法被调用时,我得到一个断言错误。

当我通过将--pdb 选项传递给它来调试pytest 时,我通过检查MagicMock() 对象的.method.called 属性来验证它“没有”被调用,但是当我检查MagicMock() 对象的@ 987654327@ 属性,我看到它实际上被调用了。

这里有一个简单的例子来说明我的意思:

test.py

import module

def test_Calling(mocker):
    mocker.patch('module.Called', autospec=True)

    module.Calling('argument')

    module.Called.assert_called_once_with('argument')
    module.Called.check_me.assert_called_once()

模块.py

class Calling(object):
    def __init__(self, argument):
        called_instance = Called(argument)
        called_instance.check_me()

class Called(object):
    def __init__(self, argument):
        pass

    def check_me(self):
        pass

这里是 pytest/pdb 会话:

(venv) C:\pytest-issue>pytest --pdb test.py
============================= test session starts =============================
platform win32 -- Python 2.7.12, pytest-3.0.6, py-1.4.32, pluggy-0.4.0
rootdir: C:\pytest-issue, inifile:
plugins: mock-1.5.0
collected 1 items

test.py F
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

mocker = <pytest_mock.MockFixture object at 0x000000000431B2E8>

    def test_Calling(mocker):
        mocker.patch('module.Called', autospec=True)

        module.Calling('argument')

        module.Called.assert_called_once_with('argument')
>       module.Called.check_me.assert_called_once()

test.py:9:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_mock_self = <MagicMock name='Called.check_me' spec='instancemethod' id='70367608'>

    def assert_called_once(_mock_self):
        """assert that the mock was called only once.
        """
        self = _mock_self
        if not self.call_count == 1:
            msg = ("Expected '%s' to have been called once. Called %s times." %
                   (self._mock_name or 'mock', self.call_count))
>           raise AssertionError(msg)
E           AssertionError: Expected 'check_me' to have been called once. Called 0 times.

venv\lib\site-packages\mock\mock.py:915: AssertionError
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> c:\pytest-issue\venv\lib\site-packages\mock\mock.py(915)assert_called_once()
-> raise AssertionError(msg)
(Pdb) up
> c:\pytest-issue\test.py(9)test_Calling()
-> module.Called.check_me.assert_called_once()
(Pdb) module.Called.method_calls
[call().check_me()]
(Pdb) module.Called.check_me.called
False

对于我的一生,我不确定自己做错了什么。在这种情况下,我需要断言.Called.method_calls 吗?如果是这样,那看起来我必须在我的测试中加入很多逻辑,这是不可取的。

【问题讨论】:

    标签: python unit-testing mocking pytest


    【解决方案1】:

    所以,原来我对你如何测试一个补丁模块一无所知。

    import module
    
    def test_Calling(mocker):
        mock_Called = mocker.patch('module.Called')
    
        module.Calling('argument')
    
        mock_called.assert_has_calls([
            mocker.call('argument'),
            mocker.call().check_me()])
    

    这里要考虑的重要事项是您需要存储 mocker.patch 的返回值,因为这将提供对在 module.Called 上实例化和修补的 MagicMock 对象的引用。接下来,当您希望测试是否正在调用实例方法时,您应该在MagicMock 实例上使用assert_has_calls 方法,并传递给它call() 反映正在调用的参数。 call() 本身指的是__new__/__init__ 调用,call().method 指的是针对实例方法的调用。

    自从弄清楚这一点后,我已经能够非常成功地使用pytest-mock 模块。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 2019-11-12
      相关资源
      最近更新 更多