Python 如何获取一个模拟对象的多个实例

Python 如何获取一个模拟对象的多个实例,python,unit-testing,mocking,Python,Unit Testing,Mocking,我有一个正在测试B的系统,它使用一些a和一些我想要模拟的昂贵函数,但B依赖于获得a的多个实例 说:“如果类被实例化多次,那么每次都可以使用side_effect返回一个新的mock。”但我不明白,如何:( 我将如何更改此示例: import time class A: def say_hi(self): print("lets do something horribly expensive") time.sleep(2) class B: de

我有一个正在测试B的系统,它使用一些a和一些我想要模拟的昂贵函数,但B依赖于获得a的多个实例

说:“如果类被实例化多次,那么每次都可以使用side_effect返回一个新的mock。”但我不明白,如何:(

我将如何更改此示例:

import time

class A:
    def say_hi(self):
        print("lets do something horribly expensive")
        time.sleep(2)

class B:
    def __init__(self):
        self.a_map = {}
    def get_a(self):
        a = A()
        a.say_hi()
        self.a_map[a] = True

with patch('__main__.A') as mockA:
    b = B()
    def side_effect():
        # return DEFAULT  # no success
        return mockA  # no success neither
        # return mockA.clone()  # :(
    mockA.side_effect = side_effect  # no help
    # mockA.side_effect = [DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT]  # nope
    # mockA.side_effect = [mockA, mockA, mockA, mockA, mockA]  # nope
    # mockA.side_effect = [DEFAULT, mockA, mockA, mockA, mockA]  # nope, but hey! I get 2 instances in my key set now!
    # mockA.side_effect = [DEFAULT, mockA, mockA.clone(), mockA.clone().clone(), mockA.clone().clone().clone()]  # would work, but hey, seriously?

    for _ in range(5):
        b.get_a()
    print(b.a_map)
    assert len(b.a_map) == 5
这将产生以下输出:

{<MagicMock name='A' id='139998588645520'>: True}
Traceback (most recent call last):
  File "<stdin>", line 11, in <module>
AssertionError
{:True}
回溯(最近一次呼叫最后一次):
文件“”,第11行,在
断言错误

(没有模仿,断言成功了,但需要10秒。)

那么你模仿的是错误的东西。如果说“嗨”是你想要模仿的昂贵部分,那么就模仿它。这样你就不必去处理副作用了

with patch('__main__.A.say_hi'):
    b = B()
    for _ in range(5):
        b.get_a()
    print(b.a_map)
    assert len(b.a_map) == 5
要明确回答“创建具有副作用的单独模拟实例”的问题,可以指定mock作为要返回的对象

from mock import Mock
with patch('__main__.A') as mockA:
    b = B()
    mockA.side_effect = Mock
    for _ in range(5):
        b.get_a()
    print(b.a_map)
    assert len(b.a_map) == 5
嗯,你的提示#1在我的情况下可能会有所帮助,但是说#hi()的那一个实际上是一组都可以访问数据库的方法,所以我尝试了提示#2和heureka!它解决了我的问题:)Thanx