在模拟上调用python builtin dict

时间:2015-02-06 08:31:42

标签: python dictionary mocking

我希望能够设置一个模拟,允许我在应用内置dict方法时返回一些内容。

我尝试使用__iter__无济于事。我似乎无法得到任何东西,只有一本空字典:

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

2 个答案:

答案 0 :(得分:3)

来自dict documentation

  

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

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调用中获取预定义的字典。

答案 1 :(得分:2)

实际上我觉得你需要这样做:

mocked_object.keys.return_value.__iter__.return_value = [1, 2, 3]

这样,dict方法将为您提供一个包含这些键的对象,以及getattr(mocked_object, '1')(因此,另一个模拟方法)的结果作为值。我想如果你想要对结果进行更多控制,你也可以通过模拟keys()方法做你想做的事。