如何获取一个Mock对象的许多实例

时间:2013-08-14 04:26:02

标签: python unit-testing mocking

我有一个正在测试的系统B,它使用了一些带有一些我想要模拟的昂贵功能的A,但B依赖于获取A的多个实例。

http://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch说:“如果多次实例化类,你可以使用side_effect每次返回一个新的模拟。”但我不明白,如何:(

我如何更改此示例:

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

(没有嘲笑断言成功但需要10秒。)

1 个答案:

答案 0 :(得分:2)

那时候你在嘲笑错误的事情。如果say_hi是你想要嘲笑的昂贵部分,那就嘲笑它。那你就不必乱用side_effects了。

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

要明确回答“使用side_effects创建单独的模拟实例”的问题,您可以将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