Best way to override FastAPI dependencies for testing with a different dependency for each test
Solution 1:
This is what I use myself to override dependencies in my tests. You have to use it as a context manager with a with
statement (See examples below). Upon entering the context it saves existing overrides it encounters. These will be restored when exiting the context.
import typing
from fastapi import FastAPI
class DependencyOverrider:
def __init__(
self, app: FastAPI, overrides: typing.Mapping[typing.Callable, typing.Callable]
) -> None:
self.overrides = overrides
self._app = app
self._old_overrides = {}
def __enter__(self):
for dep, new_dep in self.overrides.items():
if dep in self._app.dependency_overrides:
# Save existing overrides
self._old_overrides[dep] = self._app.dependency_overrides[dep]
self._app.dependency_overrides[dep] = new_dep
return self
def __exit__(self, *args: typing.Any) -> None:
for dep in self.overrides.keys():
if dep in self._old_overrides:
# Restore previous overrides
self._app.dependency_overrides[dep] = self._old_overrides.pop(dep)
else:
# Just delete the entry
del self._app.dependency_overrides[dep]
You can use it like this in your tests:
from app.main import app
from fastapi.testclient import TestClient
def test_override_in_items(client: TestClient):
with DependencyOverrider(app, overrides={common_parameters: override_dependency}):
response = client.get("/items/")
assert response.status_code == 200
assert response.json() == {
"message": "Hello Items!",
"params": {"q": None, "skip": 5, "limit": 10},
}
Or one could use it as a fixture in pytest:
@pytest.fixture(scope="function")
def faked_common_parameters():
with DependencyOverrider(
app, overrides={common_parameters: override_dependency}
) as overrider:
yield overrider
def test_override_in_items(client: TestClient, faked_common_parameters):
# Running with the overridden dependency
response = client.get("/items/")
assert response.status_code == 200
assert response.json() == {
"message": "Hello Items!",
"params": {"q": None, "skip": 5, "limit": 10},
}