No longer works with starlette/fastapi TestClient
Follow-up of https://github.com/Colin-b/pytest_httpx/issues/144#issuecomment-2071887265
The following example works with pytest-httpx 0.26 but fails with pytest-httpx 0.30:
import fastapi
import httpx
import pytest
import pytest_asyncio
import pytest_httpx
@pytest_asyncio.fixture
async def client() -> fastapi.FastAPI:
app = fastapi.FastAPI()
@app.get("/")
def get() -> None:
return None
async with httpx.AsyncClient(
transport=httpx.ASGITransport(app=app),
base_url="http://test",
) as api_client:
yield api_client
@pytest.mark.asyncio
async def test_ok(client: httpx.AsyncClient) -> None:
response = await client.get("/")
assert response.status_code == 200
@pytest.mark.asyncio
async def test_err(
client: httpx.AsyncClient, httpx_mock: pytest_httpx.HTTPXMock
) -> None:
httpx_mock.add_response(status_code=500, text="Internal Server Error")
response = await client.get("/")
assert response.status_code == 500
httpx.ASGITransport inherits httpx.AsyncBaseTransport and pytest-httpx only mocks httpx.AsyncHTTPTransport.
I don't think it would be a good idea to mock the base transport, because its handle-Method is "abstract" and should remain so.
Maybe it should mock the asgi/wsgi transport in addition to the http transport or allow passing a list of transport classes to mock.
The Starlette test client inherts httpx.BaseTransport: https://github.com/encode/starlette/blob/master/starlette/testclient.py#L239
My current workaround is this fixture:
@pytest.fixture
def httpx_testclient_mock(monkeypatch: pytest.MonkeyPatch) -> HTTPXMock:
# This fixture is a workaound for
# https://github.com/Colin-b/pytest_httpx/issues/144
mock = HTTPXMock()
def mocked_handle_request(
transport: httpx.HTTPTransport, request: httpx.Request
) -> httpx.Response:
return mock._handle_request(transport, request) # noqa: SLF001
monkeypatch.setattr(
starlette.testclient._TestClientTransport, # noqa: SLF001
"handle_request",
mocked_handle_request,
)
return mock
Hello @sscherfke
This usage was not part of the non regression suite, and was never documented. However I agree it would be a good addition if most parameters still make sense.
I will have a look at it and see what can be done here.
Thanks for reporting
Thx, let me know if I can help you with anything <3
This feature (compatibility with fastapi TestClient) would be incredibly helpful for me. Is this something that a new contributor would be able to do quickly?
An updated work around for version 0.35.0:
@pytest.fixture
def httpx_testclient_mock(monkeypatch: pytest.MonkeyPatch, httpx_mock:pytest_httpx.HTTPXMock) -> pytest_httpx.HTTPXMock:
# This fixture is a workaround for
# https://github.com/Colin-b/pytest_httpx/issues/165
# Mock TestClient Requests
real_handle_request = starlette.testclient._TestClientTransport.handle_request
def mocked_handle_request(
transport: starlette.testclient._TestClientTransport, request: httpx.Request
) -> httpx.Response:
if httpx_mock._options.should_mock(request):
return httpx_mock._handle_request(transport, request)
return real_handle_request(transport, request)
monkeypatch.setattr(
starlette.testclient._TestClientTransport,
"handle_request",
mocked_handle_request,
)