繁体   English   中英

请求发布功能中的 Pytest 固定装置

[英]Pytest fixtures in requests post function

我试图理解此处提供的示例并模拟它以用于post方法而不是get方法。

当我测试response.status_code == 200时,一切正常。 如何在不重复代码的情况下测试多个响应状态代码(就像在这里一样?我知道需要使用固定装置,我该如何利用它们?

这就是我到现在为止的地方。

app.py

from typing import Dict, Union
from urllib.error import HTTPError

import requests
import structlog

logger = structlog.get_logger()


def get_access_token(
    url: str, client_id: str, client_secret: str, grant_type: str
) -> Union[Dict[str, Union[str, int]], None]:
    try:
        r = requests.post(
            url,
            data={"grant_type": grant_type},
            auth=(client_id, client_secret),
            verify=True,
        )
        logger.info("Fetching token status code", status_code=r.status_code)
    except HTTPError as http_err:
        logger.error("HTTP error occurred", http_error=str(http_err))
    except Exception as err:
        logger.error("Other error occurred", exception=str(err))
    else:
        # The token expires in 10800 seconds
        return r.json()
test_app.py

# contents of test_app.py, a simple test for our API retrieval
from typing import Dict, Union

import pytest
import requests

from app import get_access_token


# custom class to be the mock return value of requests.post()
class MockResponse:
    status_code = 200
    raise_for_status = None

    @staticmethod
    def json() -> Dict[str, Union[str, int]]:
        return {
            'access_token': 'fake-access-token',
            'token_type': 'fake-token-type',
            'expires_in': 10800,
        }

@pytest.fixture
def mock_response(monkeypatch):
    """Requests.post() mocked to return json."""

    def mock_post(*args, **kwargs):
        return MockResponse()

    monkeypatch.setattr(requests, "post", mock_post)


# notice our test uses the custom fixture instead of monkeypatch directly
def test_get_access_token_success(mock_response) -> None:
    result = get_access_token(
        url="https://fakeurl",
        client_id="fake-client-id",
        client_secret="fake-client-secret",
        grant_type="fake-grant-type",
    )
    assert result['access_token'] == "fake-access-token"
    assert result['token_type'] == "fake-token-type"

根据@gold_cy 的建议重写了 app.py

from typing import Dict, Union

import requests
import structlog

logger = structlog.get_logger()


def get_access_token(
    url: str,
    client_id: str,
    client_secret: str,
    grant_type: str = 'client_credentials',
) -> Dict[str, Union[str, int]]:
    try:
        r = requests.post(
            url,
            data={"grant_type": grant_type},
            auth=(client_id, client_secret),
            verify=True,
        )
        logger.info("Fetching token status code", status_code=r.status_code)
        r.raise_for_status()
        if r.status_code == 200:
            # FIXME: The token expires in 10800 seconds
            return r.json()
    except requests.exceptions.HTTPError as err:
        logger.error("HTTP error", request=err.response.text)
        raise requests.HTTPError(err)

无需过多更改代码并假设测试status_code ,您可以让您的夹具返回一个您可以提供status_coderaise_for_status的函数,以初始化您的MockResponse类。 但是,查看您的令牌代码,您似乎没有使用raise_for_status

class MockResponse:
    def __init__(self, status_code, raise_for_status):
        self.status_code = status_code
        self.raise_for_status = raise_for_status

    @staticmethod
    def json() -> Dict[str, Union[str, int]]:
        return {
            'access_token': 'fake-access-token',
            'token_type': 'fake-token-type',
            'expires_in': 10800,
        }

@pytest.fixture
def mock_response(monkeypatch):
    """Requests.post() mocked to return json."""
    def wrapper(status_code, raise_for_status=None):
        def mock_post(*args, **kwargs):
            return MockResponse(status_code, raise_for_status)

        monkeypatch.setattr(requests, "post", mock_post)

    return wrapper


def test_some_random_status_code(mock_response) -> None:
    mock_response(301)

    result = get_access_token(
        url="https://fakeurl",
        client_id="fake-client-id",
        client_secret="fake-client-secret",
        grant_type="fake-grant-type",
    )

    assert result['access_token'] == "fake-access-token"

platform darwin -- Python 3.8.9, pytest-7.0.1, pluggy-1.0.0
rootdir: ***
plugins: asyncio-0.18.3, hypothesis-6.48.1, mock-3.7.0
asyncio: mode=strict
collected 1 item                                                                                    

tests/test_manager.py 2022-07-11 07:13.35 [info     ] Fetching token status code     status_code=301
.

========================================= 1 passed in 0.04s =========================================

而不是response.status_code == 200您可以只检查response.ok 如果您想检查更多状态,那么您可以检查它是否在有效范围内。

if response.status_code in range(200, 300):
    print("response status is 2xx")

if response.status_code in (200, 201):
    pass

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM