Reputation: 6301
I'm making an HTTP request using the requests library. If the request fails, an exception is raised. For example (truncated and simplified):
main.py
from requests import get
def make_request():
r = get("https://httpbin.org/get")
r.raise_for_status()
I've written a test using pytest that mocks the request.
test_main.py
from unittest import mock
from unittest.mock import patch
import pytest
from requests import HTTPError
from main import make_request
@patch("main.get")
def test_main_exception(mock_get):
exception = HTTPError(mock.Mock(status=404), "not found")
mock_get(mock.ANY).raise_for_status.side_effect = exception
make_request()
However, I'm getting the following error because the exception is raised in the test—causing the test to fail.
$ pytest
...
E requests.exceptions.HTTPError: [Errno <Mock id='4352275232'>] not found
/usr/local/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/mock.py:1011: HTTPError
==================================================== 1 failed in 0.52s ====================================================
How do I assert on the behavior that occurs when an HTTP exception is raised (e.g. 404 status code)?
Upvotes: 4
Views: 5854
Reputation: 6503
Asking myself the same question I've found the answer in the FastAPI unit tests, see their GitHub repo test. Use raise_server_exceptions
parameter. Pasting a relevant bit here:
@app.get("/server-error")
def route_with_server_error():
raise RuntimeError("Oops!")
def test_override_server_error_exception_raises():
with pytest.raises(RuntimeError):
client.get("/server-error")
def test_override_server_error_exception_response():
client = TestClient(app, raise_server_exceptions=False)
response = client.get("/server-error")
assert response.status_code == 500
assert response.json() == {"exception": "server-error"}
Relevant bit from the Starlette docs:
By default the TestClient will raise any exceptions that occur in the application. Occasionally you might want to test the content of 500 error responses, rather than allowing client to raise the server exception. In this case you should use client = TestClient(app, raise_server_exceptions=False).
Upvotes: -1
Reputation: 6301
Use the pytest.raises
context manager to capture the exception and assert on the error message. For example:
with pytest.raises(HTTPError) as error_info:
make_request()
assert error_info == exception
Full example:
test_main.py
from unittest import mock
from unittest.mock import patch
import pytest
from requests import HTTPError
from main import make_request
@patch("main.get")
def test_main_exception(mock_get):
exception = HTTPError(mock.Mock(status=404), "not found")
mock_get(mock.ANY).raise_for_status.side_effect = exception
with pytest.raises(HTTPError) as error_info:
make_request()
assert error_info == exception
See pytest - Assertions about expected exceptions for more info.
Upvotes: 4