簡體   English   中英

修補函數的assert_call_with

[英]assert_called_with of patched function

我正在嘗試斷言包裝在另一個函數內的補丁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? 在test_get_data中“ mocked_response_200”是未知的。
我在這里檢查了其他帖子這是接近的,但答案使用了不同的補丁方法。 任何幫助將不勝感激。

您正在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_callablemock.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作為參數傳遞到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')]

單元測試是一次測試一個基本組件。 因此,在內部調用的所有其他組件都需要在其他測試中進行測試。

如果您只想斷定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關鍵字來檢查返回的響應是否為processing_properly。

mock_process_response是一個MagicMock對象,將阻止process_response調用,因此將mock_get需要mock_get定義要定義的jsonstatus_code

編輯:為process_response添加了模擬。

首先,非常感謝@ 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_gettest_get_data呢。 但是使用這種組合,我既可以斷言修補的request.get的輸入,又可以返回所需的響應,以防止在響應處理期間引發任何錯誤。

編輯:代碼格式

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM