Reputation: 1366
I have the following structure for my code which is a fastapi app:
/repo
/src
main.app
/routes
/resource
resource.py
/repository
repository.py
/tests
/routes
/resource
resource_test.py
/src/routes/resource/resource.py
def get_repository() -> Repository:
return repository
RepositoryDep = Annotated[Repository, Depends(get_repository)]
router = APIRouter()
@router.get("/")
def list(repo: RepositoryDep) -> list[Alumno]:
return repo.list()
/src/repository/repository.py
class Repository:
...
repository = Repository()
Then I have some tests for my router like this tests/routes/resource/resource.py
client = TestClient(app)
def test_get_resources(mocker) -> None:
mock_repo = MagicMock(Repository)
mock_repo.list.return_value = [
Resource(id=1, name="Something", age=20),
Resource(id=2, name="Something2", age=22)
]
mocker.patch('src.routes.resource.resource.get_repository', return_value=mock_repo)
response = client.get(
"/resources/",
)
assert response.status_code == 200
content = response.json()
assert len(content) == 2
But this tests fails, the repository used (checked by debugging) is not the mock I set up, it's the real object.
Why is it not mocking?
Upvotes: -1
Views: 19
Reputation: 3011
The reason it doesn't work is that RepositoryDep
is created at load time, so it gets its reference to get_repository
when the application starts, long before your test actually runs.
The solution is to use FastAPI's dependency_overrides
, which are designed for this exact purpose:
def test_get_resources(mocker) -> None:
mock_repo = MagicMock(Repository)
mock_repo.list.return_value = [
Resource(id=1, name="Something", age=20),
Resource(id=2, name="Something2", age=22)
]
client.dependency_overrides = { get_repository: lambda: mock_repo }
response = client.get(
"/resources/",
)
assert response.status_code == 200
content = response.json()
assert len(content) == 2
client.dependency_overrides = {}
Upvotes: 0