2015-11-20 95 views
2

我正在寻找一种方法来模拟同一个类的多个实例。尝试从How to get many instances of one Mock object解决方案,这确实奏效。不过,我也想在我的测试用例中为模拟类的每个新实例指定属性和行为。还没有找到答案。模拟对象的多个实例

例子:

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是行不通的,因为它会使用相同的值的每个实例。

回答

3

请注意,名称由A的get_name方法返回。因此,您可以使用side_effect覆盖该方法,该方法返回调用该方法的名称。看起来你真正想要的不是多个模拟实例,而是模拟中的一个方法,根据传递给它的内容返回不同的值。

下面的代码对我的作品:

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'} 

我发现模拟文档,比较混乱,但side_effects的部分是值得弄糊涂,因为它们是模拟中最有用的功能之一。

+0

试过你的例子,它的工作原理...也有道理..谢谢 – Prachi

+0

同意混淆文档。我一直在经历它。我一直认为side_effects函数示例仅适用于功能模块。让我觉得作者不希望我们使用类和面向对象,如果他们可以避免。 – Prachi

+0

他们的例子倾向于更多地表现出它的作用,而不是展示你如何使用它,我发现。它真的很多才多艺,几乎可以做任何你想做的事,但搞清楚常常是一种挑战。 – MPlanchard