Search code examples
pythontestingdependenciesoverridingfastapi

Overriding a route dependency in FastAPI


I am using FastAPI

I have a route:

@router.post("/product", tags=["product"])
async def create_product(request: Request,
                         id_generator: IdGenerator = Depends(get_id_generator)):

I have a dependencies file.

def get_id_generator() -> IdGenerator:
    return UUIDIdGenerator()

I also have SomeOtherIdGenerator I want to use for testing. I just can't get it right.

@pytest.fixture
def test_id_generator():
    return SomeOtherIdGenerator()

@pytest.mark.asyncio
async def test_create_product(test_id_generator):
    data = '{ "a": "b" }'
    app.dependency_overrides['get_id_generator'] = lambda : test_id_generator

    client = TestClient(app)
    response = client.post("/product", json={'stuff': data})
    assert response.status_code == 201
    response_data = response.json()
    assert response_data['id'] == "some known value"

The result is that I'm still getting a UUID

Expected :'some known value'
Actual   :'06864d25-f88c-4382-9d1a-08c8e6951885'

I tested with and without the lambda

Solution

 app.dependency_overrides[get_id_generator] = test_id_generator

not

 app.dependency_overrides['get_id_generator'] = test_id_generator

or

 app.dependency_overrides['get_id_generator'] = lambda : test_id_generator

Solution

  • The way you are using the app.dependency_overrides attribute in your example (i.e., app.dependency_overrides['get_id_generator'] = lambda : test_id_generator) is wrong, as you are passing a str instead of a function as the key for the original dependency, as well as passing a lambda function instead of just another function as the value for your dependency override.

    As per FastAPI's documentation

    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.

    Working Example

    from typing import Annotated
    from fastapi import Depends, FastAPI
    from fastapi.testclient import TestClient
    
    app = FastAPI()
    
    
    async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
        return {"q": q, "skip": skip, "limit": limit}
    
    
    @app.get("/items")
    async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
        return {"message": "Hello Items!", "params": commons}
    
    
    client = TestClient(app)
    
    
    async def override_dependency(q: str | None = None):
        return {"q": q, "skip": 5, "limit": 10}
    
    
    app.dependency_overrides[common_parameters] = override_dependency
    
    
    def test_override_in_items():
        response = client.get("/items")
        assert response.status_code == 200
        assert response.json() == {
            "message": "Hello Items!",
            "params": {"q": None, "skip": 5, "limit": 10},
        }