首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法在pytest中使用pytest-mock同时验证构造和实例方法调用

无法在pytest中使用pytest-mock同时验证构造和实例方法调用
EN

Stack Overflow用户
提问于 2017-02-07 23:16:12
回答 1查看 1.3K关注 0票数 2

首先,我使用pytest-mock和pytest包来测试我正在处理的一个软件项目。

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

当我通过向pytest传递--pdb选项来调试pytest时,我通过检查MagicMock()对象的.method.called属性来验证它是否“没有”被调用,但是当我检查MagicMock()对象的.method_calls属性时,我发现它实际上是被调用的。

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

test.py

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

module.py

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

代码语言:javascript
复制
(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吗?如果是这样的话,看起来我将不得不在我的测试中加入很多逻辑,这是不可取的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-06-16 02:38:35

所以,事实证明,我对如何测试一个打了补丁的模块一无所知。

代码语言:javascript
复制
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模块了。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42093394

复制
相关文章

相似问题

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