Testing API#

Install the optional testing dependencies before importing this module:

pip install "fastapi-restly[testing]"

The testing extra installs a pytest plugin entry point, so pytest auto-loads the fixtures. If your project disables plugin autoloading, add the following line to your conftest.py:

pytest_plugins = ["fastapi_restly.pytest_fixtures"]

This imports the namespaced fixtures (restly_app, restly_client, restly_session, restly_async_session, etc.) into your test session without needing to import them individually.

class fastapi_restly.testing.RestlyTestClient(app: ASGIApp, base_url: str = 'http://testserver', raise_server_exceptions: bool = True, root_path: str = '', backend: Literal['asyncio', 'trio'] = 'asyncio', backend_options: dict[str, Any] | None = None, cookies: httpx._types.CookieTypes | None = None, headers: dict[str, str] | None = None, follow_redirects: bool = True, client: tuple[str, int] = ('testclient', 50000))#

Bases: TestClient

Custom TestClient that automatically checks response codes and provides clear error messages.

assert_status(response: Response, expected_code: int | None = None)#

Check if the response status code matches the expected code.

delete(url: URL | str, *, assert_status_code: int | None = 204, **kwargs) Response#

Make a DELETE request. Asserts the response status code matches assert_status_code (default: 204). Pass assert_status_code=None to skip the assertion.

get(url: URL | str, *, assert_status_code: int | None = 200, **kwargs) Response#

Make a GET request. Asserts the response status code matches assert_status_code (default: 200). Pass assert_status_code=None to skip the assertion.

patch(url: URL | str, *, assert_status_code: int | None = 200, **kwargs) Response#

Make a PATCH request. Asserts the response status code matches assert_status_code (default: 200). Pass assert_status_code=None to skip the assertion.

post(url: URL | str, *, assert_status_code: int | None = 201, **kwargs) Response#

Make a POST request. Asserts the response status code matches assert_status_code (default: 201). Pass assert_status_code=None to skip the assertion.

put(url: URL | str, *, assert_status_code: int | None = 200, **kwargs) Response#

Make a PUT request. Asserts the response status code matches assert_status_code (default: 200). Pass assert_status_code=None to skip the assertion.

fastapi_restly.testing.activate_savepoint_only_mode(make_session: async_sessionmaker[Any] | sessionmaker[Any]) None#

Intended for use in tests. Puts the session factory into savepoint-only mode so that no test data is ever committed to the database. Each test can roll back instantly by closing the session, leaving the database clean for the next test.

This is done with “create_savepoint” mode and a wrapper on engine.connect() that begins the outer transaction before the Session can use it. https://docs.sqlalchemy.org/en/20/orm/session_transaction.html#session-external-transaction

fastapi_restly.testing.deactivate_savepoint_only_mode(make_session: async_sessionmaker[Any] | sessionmaker[Any]) None#

Reverts the effect of activate_savepoint_only_mode. Restores the original engine.connect and disables savepoint-only mode.