【问题标题】:Python mocking, return different value every callPython模拟,每次调用返回不同的值
【发布时间】:2018-02-20 19:06:26
【问题描述】:

我正在测试一个方法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._request_loc_data() 中调用 geodata_collect.utils.loadJSON(...) 时,将返回 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]}

【问题讨论】:

  • 请提供适当的 MCVE 来证明该问题。更可能的解释是您正在打印不同模拟调用的结果。例如,print(mock.called()) 会产生什么?
  • 另外,我会使用with patch('geodata_collect.utils.loadJSON') as mock:,然后在with 块中设置mock.return_value.side_effect。但这只是我的偏好。这样,您还可以访问实际替换 loadJSON 的模拟,而不仅仅是调用该模拟的结果。
  • 是的,事实证明其中一张照片来自另一个电话。 mock.call 返回 false
  • 我希望这个问题现在更清楚了。

标签: python unit-testing mocking


【解决方案1】:

您已将调用的返回值设置为模拟对象。所以这就是将被退回的东西!您为调用该调用结果设置返回值(副作用),所以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 &lt;name&gt; 创建的模拟对象通常是一个好主意,因为您现在可以访问它来断言它是否被调用。

您也可以传入您预先创建的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 列表集。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多