Как в Python проверить, вызывается ли функция с определенным аргументом?
У меня есть кодовая база Django, которая содержит конечную точку. Конечная точка делает много вещей, и теперь я хочу проверить, вызывает ли конечная точка функцию do_metadata_request
(вставлена ниже) с определенным токеном.
def do_metadata_request(url_info, token):
metadata_url = f"{settings.META_SERVER_BASE_URL}/{url_info['dossier']}"
headers = {}
if token:
headers['Authorization'] = token
return requests.get(metadata_url, headers=headers)
После некоторого возиться я создал приведенную ниже установку. Она работает, но фактический тест выполняется в имитируемой функции, которую я определяю вне самого теста. Это не выглядит элегантно или по-питоновски. Я бы предпочел сделать assert внутри теста или, по крайней мере, определить mock_do_metadata_request внутри теста.
Кто-нибудь знает способ сделать это более элегантно?
class MockResponse:
def __init__(self, status_code, json_content=None, content=None, headers=None):
self.status_code = status_code
self.json_content = json_content
self.content = content
self.headers = headers
def json(self):
return self.json_content
MOCK_TOKEN = "Bearer " + create_test_token([settings.EXTENDED_SCOPE])
def mock_do_metadata_request(url_info, token):
assert token == MOCK_TOKEN
return MockResponse(
200,
json_content={
'access': settings.ACCESS_RESTRICTED,
'documents': [{'barcode': '123', 'access': settings.ACCESS_RESTRICTED}]
}
)
class TestFileRetrieval(TestCase):
def setUp(self):
self.c = Client()
@patch('project.metadata.do_metadata_request', side_effect=mock_do_metadata_request)
def test_token_is_passed_on_to_metadata_server(self, mock_do_metadata_request):
header = {'HTTP_AUTHORIZATION': MOCK_TOKEN}
response = self.c.get(IMG_URL, **header)
Вы можете использовать различные assert_called
, asset_called_with
и т.д. методы объекта Mock
для утверждения аргументов, с которыми был вызван макет, или вы можете использовать call_args
или call_args_list
для получения аргументов, с которыми был вызван макет. Если вам не важно, какое значение имел конкретный аргумент в вызове, вы можете использовать вместо него unittest.mock.ANY. Вы можете обратиться к этим и другим методам/атрибутам класса Mock
из документации. Реализация, которая может работать для вас, может быть написана следующим образом:
from unittest.mock import ANY
class TestFileRetrieval(TestCase):
def setUp(self):
self.c = Client()
@patch('project.metadata.do_metadata_request')
def test_token_is_passed_on_to_metadata_server(self, mock_do_metadata_request):
mock_do_metadata_request.return_value = MockResponse(
200,
json_content={
'access': settings.ACCESS_RESTRICTED,
'documents': [{'barcode': '123', 'access': settings.ACCESS_RESTRICTED}]
}
)
header = {'HTTP_AUTHORIZATION': MOCK_TOKEN}
response = self.c.get(IMG_URL, **header)
mock_do_metadata_request.assert_called_with(ANY, MOCK_TOKEN)