Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why requests raise_for_status() not called using pytest

There is a class and a method _get_authorize_token

    class StsAPI:
    
        def _get_authorize_token(self) -> str:
            try:
                resp = requests.post(settings.AUTHORIZATION_SERVICE_URL, json=self.data)
                print(resp.status_code)
                resp.raise_for_status()
                result = resp.json()
            except requests.exceptions.HTTPError:
                raise Exception('Not authorized')
            return result.get('token', {})

sts_api = StsAPI()

And a test case for _get_authorize_token

def test_raise_exception_if_request_error(
    requests_mock,
    mocker
):
    requests_mock.return_value = mocker.Mock(status_code=500)
    client = sts_api
    with pytest.raises(Exception, match='Not authorized'):
        client._get_authorize_token()

@pytest.fixture
def requests_mock(mocker):
    return mocker.patch('project.logic.connector.requests.post')

Test result

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>       with pytest.raises(Exception, match='Not authorized'):
E       Failed: DID NOT RAISE <class 'Exception'>

the print(resp.status_code) line returns status 500. Based on this I assume raise_for_status should give an error.

If change the logic to

def _get_authorize_token(self) -> str:
    resp = requests.post(settings.AUTHORIZATION_SERVICE_URL, json=self.data)
    if resp.status_code != 200:
        raise Exception('Not authorized')
    return resp

Then the test is successful

>Solution :

Since you mocked the response, accessing the raise_for_status attribute simply returns a new mock, rather than getting the actual raise_for_status method of a real response. Just like you configured the mock to produce a status_code of 500, you need to configure it to produce a method that raises the exception you expect on a status code of 500. Something like

def _raise_exception(*args):
    raise HTTPError()

requests_mock.return_value = mocker.Mock(status_code=500, raise_for_status=_raise_exception)

Now when your code-under-test calls resp.raise_for_status, your _raise_exception function will be called.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading