3 回答

TA貢獻1820條經(jīng)驗 獲得超10個贊
您正在修補模塊中的未知get對象request。您可能沒有這樣的模塊或?qū)ο蟆?/p>
您需要在request被測模塊中尋址對象。如果get_data位于模塊中views,那么您需要在views.request.get此處打補丁:
@mock.patch('views.request.get', new=mock_response_200)
從mock.patch()文檔:
目標應該是形式為 的字符串'package.module.ClassName'。目標被導入并且指定的對象替換為新對象,因此目標必須可從您正在調(diào)用的環(huán)境中導入patch()。目標是在執(zhí)行裝飾函數(shù)時導入的,而不是在裝飾時導入。
我不是在這里使用的功能都不過。只需讓模擬get()為您修補方法,然后配置該模擬對象。您當然可以將其委托給輔助函數(shù):
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)
您還可以在這樣的函數(shù)中創(chuàng)建一個魔術(shù)模擬對象,然后將該函數(shù)傳遞給new_callableon 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作為參數(shù)傳入。
兩種方法的演示(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')]

TA貢獻1804條經(jīng)驗 獲得超2個贊
首先,非常感謝@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。但是使用這種組合,我能夠同時斷言打補丁的 request.get 的輸入并返回所需的響應,以防止在響應處理期間引發(fā)任何錯誤。

TA貢獻1966條經(jīng)驗 獲得超4個贊
單元測試是一次測試一個基本組件。因此,內(nèi)部調(diào)用的每個其他組件都需要在其他測試中進行測試。
如果您只想斷言url正確傳遞,那么我建議不要使用new關(guān)鍵字
@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)
這將幫助您確定它是否被正確調(diào)用。在后面的測試中,使用new關(guān)鍵字來檢查返回的響應是否正確處理。
這mock_process_response是一個MagicMock對象,將阻止process_response被調(diào)用,因此不需要mock_get定義json或被status_code定義。
編輯:為process_response.
添加回答
舉報