starlette/tests/test_exceptions.py

110 lines
3.0 KiB
Python

from starlette.exceptions import ExceptionMiddleware, HTTPException
from starlette.responses import PlainTextResponse
from starlette.routing import Router, Path
from starlette.testclient import TestClient
import pytest
def raise_runtime_error(scope):
async def asgi(receive, send):
raise RuntimeError("Yikes")
return asgi
def not_acceptable(scope):
async def asgi(receive, send):
raise HTTPException(status_code=406)
return asgi
def not_modified(scope):
async def asgi(receive, send):
raise HTTPException(status_code=304)
return asgi
def handled_exc_after_response(scope):
async def asgi(receive, send):
response = PlainTextResponse("OK", status_code=200)
await response(receive, send)
raise HTTPException(status_code=406)
return asgi
router = Router(
routes=[
Path("/runtime_error", app=raise_runtime_error),
Path("/not_acceptable", app=not_acceptable),
Path("/not_modified", app=not_modified),
Path("/handled_exc_after_response", app=handled_exc_after_response),
]
)
app = ExceptionMiddleware(router)
client = TestClient(app)
def test_server_error():
with pytest.raises(RuntimeError):
response = client.get("/runtime_error")
allow_500_client = TestClient(app, raise_server_exceptions=False)
response = allow_500_client.get("/runtime_error")
assert response.status_code == 500
assert response.text == "Internal Server Error"
def test_debug_enabled():
app = ExceptionMiddleware(router)
app.debug = True
allow_500_client = TestClient(app, raise_server_exceptions=False)
response = allow_500_client.get("/runtime_error")
assert response.status_code == 500
assert "RuntimeError" in response.text
def test_not_acceptable():
response = client.get("/not_acceptable")
assert response.status_code == 406
assert response.text == "Not Acceptable"
def test_not_modified():
response = client.get("/not_modified")
assert response.status_code == 304
assert response.text == ""
def test_websockets_should_raise():
with pytest.raises(RuntimeError):
client.websocket_connect("/runtime_error")
def test_handled_exc_after_response():
# A 406 HttpException is raised *after* the response has already been sent.
# The exception middleware should raise a RuntimeError.
with pytest.raises(RuntimeError):
client.get("/handled_exc_after_response")
# If `raise_server_exceptions=False` then the test client will still allow
# us to see the response as it will have been seen by the client.
allow_200_client = TestClient(app, raise_server_exceptions=False)
response = allow_200_client.get("/handled_exc_after_response")
assert response.status_code == 200
assert response.text == "OK"
def test_force_500_response():
def app(scope):
raise RuntimeError()
force_500_client = TestClient(app, raise_server_exceptions=False)
response = force_500_client.get("/")
assert response.status_code == 500
assert response.text == ""