Python模拟,每次调用返回不同的值

时间:2018-02-20 19:06:27

标签: python unit-testing mocking

我正在测试一个方法geodata_collect._request_loc_data(),并在该方法中调用另一个方法geodata_collect.utils.loadJSON(...),我需要对其进行模拟,以便对第一个提到的方法进行单元测试。

我的问题是我需要geodata_collect.utils.loadJSON(...)geodata_collect._request_loc_data()内第三次调用时返回不同的值。

为了做到这一点,我一直在探索MagicMockside_effect

mock = MagicMock()
mock.side_effect = [self._create_request_dict(next_page_token=True),
    self._create_request_dict(next_page_token=True), self._create_request_dict()]

with patch('geodata_collect.utils.loadJSON',return_value=mock):
    geodata_collect._request_loc_data()

但是,当从geodata_collect.utils.loadJSON(...)内调用geodata_collect._request_loc_data()时,将返回MagicMock类,而不是实际值。

<MagicMock id='140642209064888'>

应该返回什么:

{'status': 'OK', 'next_page_token': 'Next Page EXISTS!!', 'result': [1, 2, 3, 4, 5]}
{'status': 'OK', 'next_page_token': 'Next Page EXISTS!!', 'result': [1, 2, 3, 4, 5]}
{'status': 'OK', 'result': [1, 2, 3, 4, 5]}

1 个答案:

答案 0 :(得分:4)

您已将调用的返回值设置为模拟对象。那就是将要归还的东西!您为该调用结果的调用设置了返回值(副作用),因此geodata_collect.utils.loadJSON()()

设置side_effect argument in the patch() call

results = [
    self._create_request_dict(next_page_token=True),
    self._create_request_dict(next_page_token=True),
    self._create_request_dict()]

with patch('geodata_collect.utils.loadJSON', side_effect=results):
    geodata_collect._request_loc_data()

或者在进入上下文管理器时返回的模拟对象上的side_effect attribute

with patch('geodata_collect.utils.loadJSON', side_effect=results) as load_mock:
    load_mock.side_effect = [
        self._create_request_dict(next_page_token=True),
        self._create_request_dict(next_page_token=True),
        self._create_request_dict()]
    geodata_collect._request_loc_data()

捕获模拟对象patch()上下文管理器创建as <name>通常是一个好主意,因为你现在可以访问它来断言它是否被调用。

您还可以传入您之前创建的MagicMock实例,只需将其作为第二个参数传入,或使用名称new

mock = MagicMock()
mock.side_effect = [self._create_request_dict(next_page_token=True),
    self._create_request_dict(next_page_token=True), self._create_request_dict()]

with patch('geodata_collect.utils.loadJSON', mock):  # or new=mock
    geodata_collect._request_loc_data()
然后

patch()geodata_collect.utils.loadJSON替换为该实例,并且调用它将使用side_effect列表集。