【问题标题】:How to Pythonically test whether a function is called with a certain argument in Python?如何以 Python 方式测试是否在 Python 中使用某个参数调用函数?
【发布时间】:2021-10-12 11:04:58
【问题描述】:

我有一个包含端点的 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)

所以经过一番摆弄后,我进行了以下设置。它可以工作,但它在我在测试本身之外定义的模拟函数中进行实际测试。它根本感觉不到优雅或 Pythonic。我宁愿在测试中做断言,或者至少在测试中定义 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)

【问题讨论】:

    标签: python django unit-testing mocking pytest


    【解决方案1】:

    您可以使用Mock 对象的各种assert_calledasset_called_with 等方法来断言调用模拟的参数,或者您可以使用call_argscall_args_list 来获取参数模拟被称为。如果您不在乎特定参数在调用中具有什么值,您可以使用 unittest.mock.ANY 代替它。您可以从documentation 引用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)
    

    【讨论】:

      猜你喜欢
      • 2023-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-22
      • 2013-06-03
      相关资源
      最近更新 更多