【问题标题】:Mocking Dictionary in pythonpython中的模拟字典
【发布时间】:2018-03-28 20:19:53
【问题描述】:

我是一般修补/模拟的新手,尤其是 python。我正在尝试使用以下方法修补将在测试用例中访问的字典

obj = Foo(None)
with patch.dict(obj.bar.items_dict,{TEST_DIR + '/Transparent.gif', data}):
    output = obj.create_css_for_imgs()

但我收到以下错误。请理解Foo的__init__()函数默认使barNone

AttributeError: 'NoneType' 对象没有属性 'items_dict'

类如下:

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

class Bar():
    def __init__(self, val)
        self.items_dict = {}
        self._load(val)

【问题讨论】:

  • 听起来您回答了自己的问题。
  • 我实际上想知道我应该怎么做,我猜这是因为 bar 被初始化为 None 但是在我的真实代码中,它在这个函数之前的其他地方设置......在这里我只是需要修补 bar.items_dict
  • @KennyOstrom 你能解释一下我该怎么做吗?
  • @tsar2512 你能展示你的Foo 类、导入和完整测试吗?
  • 模拟 bar 对象,而不是让它以 None 运行。您不能在 None 上设置属性。

标签: python unit-testing mocking patch


【解决方案1】:

不确定您是否需要patchPatch 更常用于“模拟”模块的功能。您可以使用Mock 对象创建用于测试的结构(使用“模拟”方法和属性)。

首先,我认为您收到错误是因为您将None 发送到 构造函数。但是NoneType 没有items_dict 属性。

这里有一个可以帮助你的小例子:

from mock import Mock

class Foo(object):

    def __init__(self, bar_val):  # type: (Bar) -> None
        self.bar = bar_val

    def get_bar_items_dict(self):  # type: () -> dict
        # just example - return items_dict of Bar object
        return self.bar.items_dict

    def create_css_for_imgs(self):  # type: () -> str
        return 'example'


class Bar(object):

    def __init__(self):
        self.items_dict = {}
        # other properties...


class TestExample(TestCase):

    def test_create_css_for_imgs(self):
        # create Mock instead Bar object and say that items_dict isn't empty dict
        bar = Mock(items_dict={'custom': 'dict'})
        # foo.bar will be 'Mock' object
        foo = Foo(bar)
        # check result of 'create_css_for_imgs' Foo object
        self.assertEqual(
            foo.create_css_for_imgs(),
            'example'
        )

        # check result of foo.bar.items_dict
        self.assertDictEqual(
            foo.get_bar_items_dict(),
            {'custom': 'dict'}
        )

让我们总结一下。您收到错误是因为您尝试获取None 类型的items_dict(看起来像:a = None a.items_dict)。 您可以创建任何用于测试的对象(使用“模拟”方法和属性),而无需“修补”原始类。示例:

one = Mock(one_propery=1)
two = Mock(one=one)
three = Mock(two=two)
three.my_method.return_value = [1, 2, 3]
# check our object
print three.two.one.one_propery # 1
print three.my_method() # [1, 2, 3]

在某些情况下,我们需要“模拟”类的方法(例如用于组测试)。在这种情况下你可以使用patch:

    mocked_create = mock.patch(
        'your_pack.your_module.Foo.create_css_for_imgs',
        return_value='changed example'
    )
    # change 'example' to 'changed example'
    mocked_create.start()
    foo = Foo(Bar())
    print foo.create_css_for_imgs()  # 'changed example'
    mocked_create.stop()

希望这会有所帮助。

【讨论】:

  • 谢谢你,这非常详细,并且很好地解释了 mock 与补丁的工作原理......我已经修复了我的代码以使用 Mock 并且它有效,但这无论如何都有帮助:)
  • @tsar2512 我很高兴能提供帮助。祝你好运;)
猜你喜欢
  • 1970-01-01
  • 2017-12-04
  • 2016-11-12
  • 1970-01-01
  • 2018-08-20
  • 2013-03-08
  • 1970-01-01
  • 2023-01-29
  • 1970-01-01
相关资源
最近更新 更多