Dependency injection with FastAPI problem

Viewed 2392

I am getting an error when using dependency_overrides https://fastapi.tiangolo.com/advanced/testing-dependencies/

I have sample project (in attachment) with the following structure:

service.py

from pydantic import BaseModel
class Service(BaseModel):
    key: int
    name: str

handler.py

from service import Service

class ServiceHandler:
    async def get_all(self):
        return [Service(**x) for x in
                [{'key': 1, 'name': 'One'},
                 {'key': 2, 'name': 'Two'}]]

factory.py

from fastapi import Depends
from handler import ServiceHandler

async def get_service_handler(handler=Depends(ServiceHandler)):
    return handler

main.py

from fastapi import FastAPI, APIRouter, Depends
import factory

router = APIRouter()
@router.get("/services/", tags=["services"])
async def get_services(handler=Depends(factory.get_service_handler)):
    return await handler.get_all()

app = FastAPI()
app.include_router(router)

and pytest+pytest-mock unit test for route:

unit_tests/test.py

import...
@pytest.fixture(scope="session", autouse=True)
def client():
    return TestClient(app)

def test_get_services(client, mocker):
    handler = ServiceHandler()
    mocker.patch.object(handler, 'get_all')
    handler.get_all.return_value = [Service(_id=None, key=1, name='Test')]
    app.dependency_overrides[factory.get_service_handler] = handler

    response = client.get("/services")

    assert response.status_code == 200
    # expected = [{'_id': None, 'key': 1, 'name': 'Test'}]
    expected = [{'_id': None, 'key': 1, 'name': 'One'}, {'_id': None, 'key': 2, 'name': 'Two'}]
    assert response.json() == expected

    app.dependency_overrides = {}

When I ran it with: pytest unit_tests/test.py I got an exception: FAILED unit_tests/test.py::test_get_services - TypeError: <handler.ServiceHandler object at 0x7fd03d813b50> is not a callable object

I tried to add call to handler.py as follows

...
class ServiceHandler:
    def __call__(self):
        pass
...

and another exception happened: FAILED unit_tests/test.py::test_get_services - AttributeError: 'NoneType' object has no attribute 'get_all'

After all, if I start the server: hypercorn main:app --reload http://127.0.0.1:8000/services/ everything works well in any way.

If I comment out the line in test.py:

...
app.dependency_overrides[factory.get_service_handler] = handler
...

then the test will work, so I guess the cause of the problem is in dependency_overrides.

depends_demo.zip

0 Answers
Related