繁体   English   中英

如何在python 3中自动指定默认为None的模拟属性?

[英]How can I autospec mock attributes that are None by default in python 3?

考虑以下代码:

import unittest
from unittest.mock import patch

class Foo(object):
    def __init__(self, bar=None):
        self.bar = bar

    def methodA(self):
        print("In methodA")

    def methodB(self):
        print("In methodB")


def my_func(bar):
    foo = Foo(bar)
    if foo.bar:
        foo.methodA()
    foo.methodB()


class MyTestCase(unittest.TestCase):
    def test_my_func(self):
        bar = None

        with patch("__main__.Foo", autospec=True) as foo:
            my_func(bar)
            foo.methodB.assert_called_once_with()


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

这个想法很简单。 我有一个函数,该函数的行为会切换是否存在实例属性。 我正在尝试编写一个单元测试,以根据属性验证仅执行某些Foo方法。

基于模拟库的补丁和自动指定文档,我认为在patch()上下文管理器中设置autospec=True就足够了。 没有。 所生成的Mock()正确地包括嘲笑methodAmethodB ,但测试失败,此错误:

======================================================================
ERROR: test_my_func (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "so.py", line 28, in test_my_func
    my_func(bar)
  File "trash.py", line 18, in my_func
    if foo.bar:
  File "/.../python3.3/unittest/mock.py", line 549, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'bar'

我确定我缺少明显的东西,但似乎无法弄清楚。 如何对my_func()

我的部分问题是对补丁行为的误解。 我设置的上下文管理器将返回__main__.Foo模拟的实例,而不是my_func()使用的同一实例 换句话说,即使我能够在没有autospec的情况下正确模拟Foo ,也无法assert_called_once_with()任何方法执行assert_called_once_with() :它不是同一对象。

一种解决方案是模拟方法本身。 这有效:

def test_my_func(self):
    bar = None
    with patch('__main__.Foo.methodB') as mock_methodB:
        my_func(bar)
        mock_methodB.assert_called_once_with()

另一种方法是修改my_func()以返回foo:

def my_func(bar):
    foo = Foo(bar)
    if foo.bar:
        foo.methodA()
    foo.methodB()
    return foo

由于该函数返回了测试中的模拟,因此以下代码应该起作用:

def test_my_func(self):
    bar = None
    with patch('__main__.Foo', spec=True, bar=None):
        foo = my_func(bar)
        assert foo.methodB.called
        assert not foo.methodA.called

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM