在模拟中调用python内置字典 - python

我希望能够设置一个模拟,使我在应用内置的dict方法时可以返回某些内容。

我尝试使用__iter__无济于事。除了空字典,我似乎什么也没得到:

import mock
mocked_object = mock.MagicMock()
mocked_object.__iter__.return_value = [1, 2, 3]
dict(mocked_object)
# {}

python大神给出的解决方案

来自dict documentation

如果给出了位置参数并且它是一个映射对象,则将使用与该映射对象相同的键值对创建一个字典。否则,位置参数必须是可迭代的对象。可迭代对象中的每个项目本身都必须是具有两个对象的可迭代对象。每个项目的第一个对象成为新字典中的键,第二个对象成为相应的值。

MagicMock对象公开keys方法只是因为它们是模拟对象,因此dict()会认为它们是映射对象。不幸的是,如果我们希望在dict上将模拟调用变成具有预定义键值的字典,则使用这种方法有点复杂。以下示例说明如何通过使用映射对象协议将dict转换为预定义的字典:

>>> m = MagicMock()
>>> d = {"a":"A", "b":"B", "c":"C"}
>>> m.keys.return_value.__iter__.return_value = ["a", "b", "c"]
>>> m.__getitem__.side_effect = ["A","B","C"]
>>> dict(m)
{'a': 'A', 'c': 'C', 'b': 'B'}
>>> #Little bit generic
>>> m.keys.return_value.__iter__.return_value = d.keys()
>>> m.__getitem__.side_effect = lambda k:d[k]
>>> dict(m)
{'a': 'A', 'c': 'C', 'b': 'B'}

两者都很难阅读,在我们的测试中,我们希望阅读更简单。

为了使dict使用迭代器代替映射,我们可以从模拟中删除keys方法并设置__iter__.return_value:

>>> del m.keys
>>> m.__iter__.return_value = [("a","A"),("b","B"),("c","C")]
>>> dict(m)
{'a': 'A', 'c': 'C', 'b': 'B'}
>>> #Little bit generic
>>> m.__iter__.return_value = d.items()
>>> dict(m)
{'a': 'A', 'c': 'C', 'b': 'B'}

恕我直言,这是一种简单而整洁的方式来设置您的模拟并从dict调用中获取预定义的词典。