Testing Dependencies with Overrides

Warning

The current page still doesn’t have a translation for this language.

But you can help translating it: Contributing.

Overriding dependencies during testing

There are some scenarios where you might want to override a dependency during testing.

You don’t want the original dependency to run (nor any of the sub-dependencies it might have).

Instead, you want to provide a different dependency that will be used only during tests (possibly only some specific tests), and will provide a value that can be used where the value of the original dependency was used.

Use cases: external service

An example could be that you have an external authentication provider that you need to call.

You send it a token and it returns an authenticated user.

This provider might be charging you per request, and calling it might take some extra time than if you had a fixed mock user for tests.

You probably want to test the external provider once, but not necessarily call it for every test that runs.

In this case, you can override the dependency that calls that provider, and use a custom dependency that returns a mock user, only for your tests.

Use the app.dependency_overrides attribute

For these cases, your FastAPI application has an attribute app.dependency_overrides, it is a simple dict.

To override a dependency for testing, you put as a key the original dependency (a function), and as the value, your dependency override (another function).

And then FastAPI will call that override instead of the original dependency.

Python 3.10+Python 3.9+Python 3.8+Python 3.10+ non-AnnotatedPython 3.8+ non-Annotated

  1. from typing import Annotated
  2. from fastapi import Depends, FastAPI
  3. from fastapi.testclient import TestClient
  4. app = FastAPI()
  5. async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
  6. return {"q": q, "skip": skip, "limit": limit}
  7. @app.get("/items/")
  8. async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
  9. return {"message": "Hello Items!", "params": commons}
  10. @app.get("/users/")
  11. async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
  12. return {"message": "Hello Users!", "params": commons}
  13. client = TestClient(app)
  14. async def override_dependency(q: str | None = None):
  15. return {"q": q, "skip": 5, "limit": 10}
  16. app.dependency_overrides[common_parameters] = override_dependency
  17. def test_override_in_items():
  18. response = client.get("/items/")
  19. assert response.status_code == 200
  20. assert response.json() == {
  21. "message": "Hello Items!",
  22. "params": {"q": None, "skip": 5, "limit": 10},
  23. }
  24. def test_override_in_items_with_q():
  25. response = client.get("/items/?q=foo")
  26. assert response.status_code == 200
  27. assert response.json() == {
  28. "message": "Hello Items!",
  29. "params": {"q": "foo", "skip": 5, "limit": 10},
  30. }
  31. def test_override_in_items_with_params():
  32. response = client.get("/items/?q=foo&skip=100&limit=200")
  33. assert response.status_code == 200
  34. assert response.json() == {
  35. "message": "Hello Items!",
  36. "params": {"q": "foo", "skip": 5, "limit": 10},
  37. }
  1. from typing import Annotated, Union
  2. from fastapi import Depends, FastAPI
  3. from fastapi.testclient import TestClient
  4. app = FastAPI()
  5. async def common_parameters(
  6. q: Union[str, None] = None, skip: int = 0, limit: int = 100
  7. ):
  8. return {"q": q, "skip": skip, "limit": limit}
  9. @app.get("/items/")
  10. async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
  11. return {"message": "Hello Items!", "params": commons}
  12. @app.get("/users/")
  13. async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
  14. return {"message": "Hello Users!", "params": commons}
  15. client = TestClient(app)
  16. async def override_dependency(q: Union[str, None] = None):
  17. return {"q": q, "skip": 5, "limit": 10}
  18. app.dependency_overrides[common_parameters] = override_dependency
  19. def test_override_in_items():
  20. response = client.get("/items/")
  21. assert response.status_code == 200
  22. assert response.json() == {
  23. "message": "Hello Items!",
  24. "params": {"q": None, "skip": 5, "limit": 10},
  25. }
  26. def test_override_in_items_with_q():
  27. response = client.get("/items/?q=foo")
  28. assert response.status_code == 200
  29. assert response.json() == {
  30. "message": "Hello Items!",
  31. "params": {"q": "foo", "skip": 5, "limit": 10},
  32. }
  33. def test_override_in_items_with_params():
  34. response = client.get("/items/?q=foo&skip=100&limit=200")
  35. assert response.status_code == 200
  36. assert response.json() == {
  37. "message": "Hello Items!",
  38. "params": {"q": "foo", "skip": 5, "limit": 10},
  39. }
  1. from typing import Union
  2. from fastapi import Depends, FastAPI
  3. from fastapi.testclient import TestClient
  4. from typing_extensions import Annotated
  5. app = FastAPI()
  6. async def common_parameters(
  7. q: Union[str, None] = None, skip: int = 0, limit: int = 100
  8. ):
  9. return {"q": q, "skip": skip, "limit": limit}
  10. @app.get("/items/")
  11. async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
  12. return {"message": "Hello Items!", "params": commons}
  13. @app.get("/users/")
  14. async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
  15. return {"message": "Hello Users!", "params": commons}
  16. client = TestClient(app)
  17. async def override_dependency(q: Union[str, None] = None):
  18. return {"q": q, "skip": 5, "limit": 10}
  19. app.dependency_overrides[common_parameters] = override_dependency
  20. def test_override_in_items():
  21. response = client.get("/items/")
  22. assert response.status_code == 200
  23. assert response.json() == {
  24. "message": "Hello Items!",
  25. "params": {"q": None, "skip": 5, "limit": 10},
  26. }
  27. def test_override_in_items_with_q():
  28. response = client.get("/items/?q=foo")
  29. assert response.status_code == 200
  30. assert response.json() == {
  31. "message": "Hello Items!",
  32. "params": {"q": "foo", "skip": 5, "limit": 10},
  33. }
  34. def test_override_in_items_with_params():
  35. response = client.get("/items/?q=foo&skip=100&limit=200")
  36. assert response.status_code == 200
  37. assert response.json() == {
  38. "message": "Hello Items!",
  39. "params": {"q": "foo", "skip": 5, "limit": 10},
  40. }

Tip

Prefer to use the Annotated version if possible.

  1. from fastapi import Depends, FastAPI
  2. from fastapi.testclient import TestClient
  3. app = FastAPI()
  4. async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
  5. return {"q": q, "skip": skip, "limit": limit}
  6. @app.get("/items/")
  7. async def read_items(commons: dict = Depends(common_parameters)):
  8. return {"message": "Hello Items!", "params": commons}
  9. @app.get("/users/")
  10. async def read_users(commons: dict = Depends(common_parameters)):
  11. return {"message": "Hello Users!", "params": commons}
  12. client = TestClient(app)
  13. async def override_dependency(q: str | None = None):
  14. return {"q": q, "skip": 5, "limit": 10}
  15. app.dependency_overrides[common_parameters] = override_dependency
  16. def test_override_in_items():
  17. response = client.get("/items/")
  18. assert response.status_code == 200
  19. assert response.json() == {
  20. "message": "Hello Items!",
  21. "params": {"q": None, "skip": 5, "limit": 10},
  22. }
  23. def test_override_in_items_with_q():
  24. response = client.get("/items/?q=foo")
  25. assert response.status_code == 200
  26. assert response.json() == {
  27. "message": "Hello Items!",
  28. "params": {"q": "foo", "skip": 5, "limit": 10},
  29. }
  30. def test_override_in_items_with_params():
  31. response = client.get("/items/?q=foo&skip=100&limit=200")
  32. assert response.status_code == 200
  33. assert response.json() == {
  34. "message": "Hello Items!",
  35. "params": {"q": "foo", "skip": 5, "limit": 10},
  36. }

Tip

Prefer to use the Annotated version if possible.

  1. from typing import Union
  2. from fastapi import Depends, FastAPI
  3. from fastapi.testclient import TestClient
  4. app = FastAPI()
  5. async def common_parameters(
  6. q: Union[str, None] = None, skip: int = 0, limit: int = 100
  7. ):
  8. return {"q": q, "skip": skip, "limit": limit}
  9. @app.get("/items/")
  10. async def read_items(commons: dict = Depends(common_parameters)):
  11. return {"message": "Hello Items!", "params": commons}
  12. @app.get("/users/")
  13. async def read_users(commons: dict = Depends(common_parameters)):
  14. return {"message": "Hello Users!", "params": commons}
  15. client = TestClient(app)
  16. async def override_dependency(q: Union[str, None] = None):
  17. return {"q": q, "skip": 5, "limit": 10}
  18. app.dependency_overrides[common_parameters] = override_dependency
  19. def test_override_in_items():
  20. response = client.get("/items/")
  21. assert response.status_code == 200
  22. assert response.json() == {
  23. "message": "Hello Items!",
  24. "params": {"q": None, "skip": 5, "limit": 10},
  25. }
  26. def test_override_in_items_with_q():
  27. response = client.get("/items/?q=foo")
  28. assert response.status_code == 200
  29. assert response.json() == {
  30. "message": "Hello Items!",
  31. "params": {"q": "foo", "skip": 5, "limit": 10},
  32. }
  33. def test_override_in_items_with_params():
  34. response = client.get("/items/?q=foo&skip=100&limit=200")
  35. assert response.status_code == 200
  36. assert response.json() == {
  37. "message": "Hello Items!",
  38. "params": {"q": "foo", "skip": 5, "limit": 10},
  39. }

Tip

You can set a dependency override for a dependency used anywhere in your FastAPI application.

The original dependency could be used in a path operation function, a path operation decorator (when you don’t use the return value), a .include_router() call, etc.

FastAPI will still be able to override it.

Then you can reset your overrides (remove them) by setting app.dependency_overrides to be an empty dict:

  1. app.dependency_overrides = {}

Tip

If you want to override a dependency only during some tests, you can set the override at the beginning of the test (inside the test function) and reset it at the end (at the end of the test function).