我正在尝试断言包裹在另一个函数中的修补request.get()调用的输入。
def get_data(*args):
# logic to define url, based on '*args'
url = 'some_url?arg1&arg3'
# call I want to patch and assert the url of
response = request.get(url)
# process response
stuff = 'processed_response'
return stuff
测试脚本:
def mock_response_200(url):
response = mock.MagicMock()
response.status_code = 200
response.json = mock.Mock(return_value={
0: {'key1': 'value1', 'key2': 'value2'}
})
return response
@mock.patch('request.get', new=mock_response_200)
def test_get_data():
arg1 = 'arg1'
arg2 = None
arg3 = 'arg3'
stuff = get_data(arg1, arg2, arg3)
# <assert input arguments of patched function here>
如何断言传递给Mocked_Response_200的URL?Mocked_Response_200在test_get_data中不"知道"。
我已经检查了此处的其他帖子,但答案使用了不同的补丁方法。任何帮助将不胜感激。
您正在修补request
模块中未知的get
对象。您可能没有这样的模块或对象。
您需要在测试的模块中解决request
对象。如果get_data
生活在模块views
中,则需要在此处修补views.request.get
:
@mock.patch('views.request.get', new=mock_response_200)
来自mock.patch()
文档:
target 应该是表格
'package.module.ClassName'
中的字符串。目标是导入的,指定的对象替换为新对象,因此目标必须从您从中调用patch()
的环境中导入。在执行装饰功能时而不是在装饰时导入目标。
但是,我根本不会在这里使用函数。只需为您模拟修补get()
方法,然后配置该模拟对象即可。您当然可以将其委派给辅助功能:
def config_response_200_mock(request_get):
response = request_get.return_value
response.status_code = 200
response.json.return_value = {
0: {'key1': 'value1', 'key2': 'value2'}
}
return response
@mock.patch('views.request.get')
def test_get_data(request_get):
response_mock = config_response_200_mock(request_get)
arg1 = 'arg1'
arg2 = None
arg3 = 'arg3'
stuff = get_data(arg1, arg2, arg3)
您还可以在此功能中创建一个魔术模拟对象,然后将函数传递给new_callable
上的mock.patch()
:
def response_200_mock():
get_mock = mock.MagicMock()
response = get_mock.return_value
response.status_code = 200
response.json.return_value = {
0: {'key1': 'value1', 'key2': 'value2'}
}
return get_mock
@mock.patch('views.request.get', new_callable=response_200_mock)
def test_get_data(request_get):
arg1 = 'arg1'
arg2 = None
arg3 = 'arg3'
stuff = get_data(arg1, arg2, arg3)
无论哪种方式,用于修补request.get
的对象作为参数传递到test_get_data
中。
两种方法的演示(使用patch
作为上下文管理器而不是装饰符,但原理是相同的:
>>> def config_response_200_mock(request_get):
... response = request_get.return_value
... response.status_code = 200
... response.json.return_value = {
... 0: {'key1': 'value1', 'key2': 'value2'}
... }
... return response
...
>>> with mock.patch('__main__.request.get') as request_get:
... response_mock = config_response_200_mock(request_get)
... arg1 = 'arg1'
... arg2 = None
... arg3 = 'arg3'
... stuff = get_data(arg1, arg2, arg3)
...
>>> stuff
'processed_response'
>>> response_mock.json()
{0: {'key1': 'value1', 'key2': 'value2'}}
>>> request_get.mock_calls
[call('some_url?arg1&arg3')]
>>> def response_200_mock():
... get_mock = mock.MagicMock()
... response = get_mock.return_value
... response.status_code = 200
... response.json.return_value = {
... 0: {'key1': 'value1', 'key2': 'value2'}
... }
... return get_mock
...
>>> with mock.patch('__main__.request.get', new_callable=response_200_mock) as request_get:
... arg1 = 'arg1'
... arg2 = None
... arg3 = 'arg3'
... stuff = get_data(arg1, arg2, arg3)
...
>>> stuff
'processed_response'
>>> request_get.return_value.json()
{0: {'key1': 'value1', 'key2': 'value2'}}
>>> request_get.mock_calls
[call('some_url?arg1&arg3')]
首先,非常感谢 @ja8zyjits和@martijn Pieters的帮助。
对我有用的解决方案看起来如下:
@mock.patch('request.get', side_effect=mock_response_200)
def test_get_data(mock_get):
arg1 = 'arg1'
arg2 = None
arg3 = 'arg3'
expected_url = 'some_url?arg1&arg3'
stuff = get_data(arg1, arg2, arg3)
mock_get.assert_called_with(url)
我不能说我完全理解将mock_response_200
作为'side_effect'
和将mock_get
传递给test_get_data
的相互作用。但是,使用这种组合,我既可以主张修补的请求的输入。
编辑:代码格式
UNITSEST一次测试一个基本组件。因此,需要在其他测试中测试任何其他所调用的组件。
如果您只想正确传递url
,那么我建议不要使用new
关键字
@mock.patch('module.process_response')
@mock.patch('module.request.get')
def test_get_data(mock_get, mock_process_response):
arg1 = 'arg1'
arg2 = None
arg3 = 'arg3'
url = "what ever url"
stuff = get_data(arg1, arg2, arg3)
mock_get.assert_called_with(url)
这将帮助您确定是否正确调用它。在以后的测试中,使用new
关键字检查是否处理返回的响应。
mock_process_response
是MagicMock
对象,将防止process_response
被调用,因此不要求mock_get
定义json
或status_code
。
编辑:添加了process_response
的模拟。