Skip to content

Bug: Test Clients raise_server_exceptions doesn't work as intended #4180

@NewSouthMjos

Description

@NewSouthMjos

Description

litestar.testing.AsyncTestClient and litestar.testing.TestClient has param:

raise_server_exceptions – Flag for the underlying test client to raise server exceptions instead of wrapping them in an HTTP response.

This flag doesn't do anything - still, the test test_fake in my MCVE is passing.
I have digged in a bit. Problem is:
The underlying TestClientTransport.handle_request doesnt ever catch exception (except BaseException as exc:), and self.raise_server_exceptions dont work. The reason why TestClientTransport doesnt catch exceptions that all exception is handled by ExceptionHandlerMiddleware every time, and ExceptionHandlerMiddleware does not re-rise exception.

For example, in Starlette exception handler there is this kind of re-rise starlette.starlette.middlewar.errors.py:ExceptionHandlerMiddleware:async def call, line 187:

            # We always continue to raise the exception.
            # This allows servers to log the error, or allows test clients
            # to optionally raise the error within the test case.
            raise exc

I can see, that in future v3 version ExceptionHandlerMiddleware will be deprecated. So, questions are:

  1. Can we make a patch for v2 for re-rize exception in middleware? I have tests it - just added raise exc at the end of async def handle_request_exception for middleware - it works then as intended - test crashes with log, on normal usage - there is response from middleware, and server gives error logs. I can make PR, but i guess there is more underlying logic that needs to be taken into account.
  2. In v3 branch i can still see ExceptionHandlerMiddleware there in code. Will the problem with raise_server_exceptions will be solved somehow in v3?

URL to code causing the issue

No response

MCVE

### main.py
from litestar import Litestar, get
@get(path="/error-check")
async def error_check() -> str:
    raise ValueError("I should see this")
    return "healthy"

app = Litestar(route_handlers=[error_check])

return app


###pytest part
###conftest.py
import pytest

from litestar.testing import AsyncTestClient

from main import app

@pytest.fixture()
async def admin_client() -> AsyncGenerator[AsyncClient, None]:
    async with AsyncTestClient(
        app=app,
        raise_server_exceptions=True # defalt is True - just to be unambiguous
    ) as client:
        yield client

###test.py
from httpx import AsyncTestClient
import pytest

pytestmark = pytest.mark.anyio


async def test_fake(client: AsyncClient):
    response = await client.get("/check")
    assert True

Steps to reproduce

  1. Use MCVE code
  2. Run pytest .
  3. Tests pass, but it should not

Screenshots

No response

Logs


Litestar Version

2.16

Platform

  • Linux
  • Mac
  • Windows
  • Other (Please specify in the description above)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Bug 🐛This is something that is not working as expected

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions