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

Car*_*rdh 3 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()
Run Code Online (Sandbox Code Playgroud)

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

<MagicMock id='140642209064888'>
Run Code Online (Sandbox Code Playgroud)

应该返回什么:

{'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]}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 5

您已将调用的返回值设置为模拟对象。这就是返回的内容!您可以为该调用结果的调用设置返回值(副作用),因此geodata_collect.utils.loadJSON()()

side_effectpatch()调用中设置参数

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()
Run Code Online (Sandbox Code Playgroud)

或进入上下文管理器时返回的模拟对象上的side_effect属性

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()
Run Code Online (Sandbox Code Playgroud)

无论如何,捕获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()
Run Code Online (Sandbox Code Playgroud)

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