Как в 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)
Вернуться на верх