模拟对象的多个实例
Multiple instances of mock object
我正在寻找一种方法来模拟同一 class 的多个实例。尝试了 How to get many instances of one Mock object 的解决方案,确实有效。但是,我还想在我的测试用例中为模拟 class 的每个新实例指定属性和行为。还没有找到答案。
示例:
class A:
def __init__(self, name):
self.name = name
def get_name(self):
print("hi " + self.name)
return self.name
class B:
def __init__(self):
self.a_map = {}
def get_all_a_values(self, names):
for name in names:
a = A(name)
self.a_map[a] = a.get_name()
with mock.patch('__main__.A') as mockA:
b = B()
mockA.side_effect = mock.Mock
names = ['person0', 'person1', 'person2', 'person3', 'person4']
b.get_all_a_values(names)
print(b.a_map)
assert len(b.a_map) == 5
如何更改此代码,以便在创建 mockA 的实例时,它还设置实例的名称 属性?例如我需要此代码的输出类似于:
{<Mock id='13609360'>: 'person0', <Mock id='13608720'>: 'person1', <Mock id='13610128'>: 'person2', <Mock id='13609744'>: 'person3', <Mock id='13608976'>: 'person4'}
设置 mockA.get_name.return_value 将不起作用,因为它将为每个实例使用相同的值。
请注意,名称是由 A 的 get_name
方法返回的。因此,您可以使用 side_effect 覆盖该方法,returns 调用该方法的名称。看起来你真正想要的不是多个模拟实例,而是模拟中的一个方法,returns 根据传递给它的内容不同的值。
以下代码对我有用:
import mock
class A:
def __init__(self, name):
self.name = name
def get_name(self):
print("hi " + self.name)
return self.name
class B:
def __init__(self):
self.a_map = {}
def get_all_a_values(self, names):
for name in names:
a = A(name)
self.a_map[a] = a.get_name()
def side_effect(name):
mm = mock.MagicMock()
mm.get_name.return_value = name
return mm
with mock.patch('__main__.A') as mockA:
b = B()
mockA.side_effect = side_effect
names = ['person0', 'person1', 'person2', 'person3', 'person4']
b.get_all_a_values(names)
print(b.a_map)
assert len(b.a_map) == 5
当我运行这个时,我的输出是:
{<MagicMock id='4491688656'>: 'person0', <MagicMock id='4491693264'>: 'person1', <MagicMock id='4491757456'>: 'person4', <MagicMock id='4491722960'>: 'person2', <MagicMock id='4491742224'>: 'person3'}
我发现 mock 文档相对比较混乱,但是 side_effects 上的部分值得一读,因为它们是 mock 中最有用的功能之一。
我正在寻找一种方法来模拟同一 class 的多个实例。尝试了 How to get many instances of one Mock object 的解决方案,确实有效。但是,我还想在我的测试用例中为模拟 class 的每个新实例指定属性和行为。还没有找到答案。
示例:
class A:
def __init__(self, name):
self.name = name
def get_name(self):
print("hi " + self.name)
return self.name
class B:
def __init__(self):
self.a_map = {}
def get_all_a_values(self, names):
for name in names:
a = A(name)
self.a_map[a] = a.get_name()
with mock.patch('__main__.A') as mockA:
b = B()
mockA.side_effect = mock.Mock
names = ['person0', 'person1', 'person2', 'person3', 'person4']
b.get_all_a_values(names)
print(b.a_map)
assert len(b.a_map) == 5
如何更改此代码,以便在创建 mockA 的实例时,它还设置实例的名称 属性?例如我需要此代码的输出类似于:
{<Mock id='13609360'>: 'person0', <Mock id='13608720'>: 'person1', <Mock id='13610128'>: 'person2', <Mock id='13609744'>: 'person3', <Mock id='13608976'>: 'person4'}
设置 mockA.get_name.return_value 将不起作用,因为它将为每个实例使用相同的值。
请注意,名称是由 A 的 get_name
方法返回的。因此,您可以使用 side_effect 覆盖该方法,returns 调用该方法的名称。看起来你真正想要的不是多个模拟实例,而是模拟中的一个方法,returns 根据传递给它的内容不同的值。
以下代码对我有用:
import mock
class A:
def __init__(self, name):
self.name = name
def get_name(self):
print("hi " + self.name)
return self.name
class B:
def __init__(self):
self.a_map = {}
def get_all_a_values(self, names):
for name in names:
a = A(name)
self.a_map[a] = a.get_name()
def side_effect(name):
mm = mock.MagicMock()
mm.get_name.return_value = name
return mm
with mock.patch('__main__.A') as mockA:
b = B()
mockA.side_effect = side_effect
names = ['person0', 'person1', 'person2', 'person3', 'person4']
b.get_all_a_values(names)
print(b.a_map)
assert len(b.a_map) == 5
当我运行这个时,我的输出是:
{<MagicMock id='4491688656'>: 'person0', <MagicMock id='4491693264'>: 'person1', <MagicMock id='4491757456'>: 'person4', <MagicMock id='4491722960'>: 'person2', <MagicMock id='4491742224'>: 'person3'}
我发现 mock 文档相对比较混乱,但是 side_effects 上的部分值得一读,因为它们是 mock 中最有用的功能之一。