Warning
This is the documentation of the older version 0.14.0
. See latest for current release.
Mock HTTPX - Version 0.14.0
To mock out HTTPX
and/or HTTP Core
, use the respx.mock
decorator / context manager.
Optionally configure built-in assertion checks and base URL
with respx.mock(...)
.
Using the Decorator
import httpx
import respx
@respx.mock
def test_something():
request = respx.get("https://foo.bar/", content="foobar")
response = httpx.get("https://foo.bar/")
assert request.called
assert response.status_code == 200
assert response.text == "foobar"
Using the Context Manager
import httpx
import respx
with respx.mock:
request = respx.get("https://foo.bar/", content="foobar")
response = httpx.get("https://foo.bar/")
assert request.called
assert response.status_code == 200
assert response.text == "foobar"
NOTE
You can also start and stop mocking HTTPX
manually, by calling respx.start()
and respx.stop()
.
Using the mock Transports
The built-in transports are the base of all mocking and patching in RESPX.
In fact, respx.mock
is an actual instance of MockTransport
.
MockTransport
import httpx
import respx
mock_transport = respx.MockTransport()
request = mock_transport.get("https://foo.bar/", content="foobar")
with mock_transport:
response = httpx.get("https://foo.bar/")
assert request.called
assert response.status_code == 200
assert response.text == "foobar"
SyncMockTransport
If you don't need to patch the original HTTPX
/HTTP Core
transports, then use the SyncMockTransport
or AsyncMockTransport
directly, by passing the transport
arg when instantiating your HTTPX
client, or alike.
import httpx
import respx
mock_transport = respx.SyncMockTransport()
request = mock_transport.get("https://foo.bar/", content="foobar")
with httpx.Client(transport=mock_transport) as client:
response = client.get("https://foo.bar/")
assert request.called
assert response.status_code == 200
assert response.text == "foobar"
AsyncMockTransport
import httpx
import respx
mock_transport = respx.AsyncMockTransport()
request = mock_transport.get("https://foo.bar/", content="foobar")
async with httpx.AsyncClient(transport=mock_transport) as client:
response = await client.get("https://foo.bar/")
assert request.called
assert response.status_code == 200
assert response.text == "foobar"
NOTE
The mock transports takes the same configuration arguments as the decorator / context manager.
Global Setup & Teardown
pytest
# conftest.py
import pytest
import respx
@pytest.fixture
def mocked_api():
with respx.mock(base_url="https://foo.bar") as respx_mock:
respx_mock.get("/users/", content=[], alias="list_users")
...
yield respx_mock
# test_api.py
import httpx
def test_list_users(mocked_api):
response = httpx.get("https://foo.bar/users/")
request = mocked_api["list_users"]
assert request.called
assert response.json() == []
Tip
Use a session scoped fixture @pytest.fixture(scope="session")
when your fixture contains multiple
endpoints that not necessary gets called by a single test case, or disable
the built-in assert_all_called
check.
unittest
# testcases.py
class MockedAPIMixin:
def setUp(self):
self.mocked_api = respx.mock(base_url="https://foo.bar")
self.mocked_api.get("/users/", content=[], alias="list_users")
...
self.mocked_api.start()
def tearDown(self):
self.mocked_api.stop()
# test_api.py
import unittest
import httpx
from .testcases import MockedAPIMixin
class MyTestCase(MockedAPIMixin, unittest.TestCase):
def test_list_users(self):
response = httpx.get("https://foo.bar/users/")
request = self.mocked_api["list_users"]
assert request.called
assert response.json() == []
Tip
Use setUpClass
and tearDownClass
when you mock multiple endpoints that not
necessary gets called by a single test method, or disable
the built-in assert_all_called
check.
Async Support
You can use respx.mock
in both sync and async contexts to mock out HTTPX
responses.
pytest
@respx.mock
@pytest.mark.asyncio
async def test_something():
async with httpx.AsyncClient() as client:
request = respx.get("https://foo.bar/", content="foobar")
response = await client.get("https://foo.bar/")
assert request.called
assert response.text == "foobar"
@pytest.mark.asyncio
async def test_something():
async with respx.mock:
async with httpx.AsyncClient() as client:
request = respx.get("https://foo.bar/", content="foobar")
response = await client.get("https://foo.bar/")
assert request.called
assert response.text == "foobar"
Session Scoped Fixtures
If a session scoped RESPX fixture is used in an async context, you also need to broaden the pytest-asyncio
event_loop fixture.
You can use the session_event_loop
utility for this.
# conftest.py
import pytest
import respx
from respx.fixtures import session_event_loop as event_loop # noqa: F401
@pytest.fixture(scope="session")
async def mocked_api(event_loop): # noqa: F811
async with respx.mock(base_url="https://foo.bar") as respx_mock:
...
yield respx_mock
unittest
import asynctest
class MyTestCase(asynctest.TestCase):
@respx.mock
async def test_something(self):
async with httpx.AsyncClient() as client:
request = respx.get("https://foo.bar/", content="foobar")
response = await client.get("https://foo.bar/")
assert request.called
assert response.text == "foobar"
async def test_something(self):
async with respx.mock:
async with httpx.AsyncClient() as client:
request = respx.get("https://foo.bar/", content="foobar")
response = await client.get("https://foo.bar/")
assert request.called
assert response.text == "foobar"