Description
I'm not sure here is the best place for this question as it's more related to testing and unittest
rather than FastAPI. However, maybe one of you had the same problem and can recommend a solution.
I want to write tests for my api endpoints which have security dependency at the include_router
level.
Below I highlight the important parts of the important files.
The security function gets the api key from header and checks it against the database; it returns the client or raise a 401 http exception.
# repo/app/api/security.py
from fastapi import Security, HTTPException
from fastapi.security import APIKeyHeader
from app.models import Client
async def get_client(
client_id: str = Security(APIKeyHeader(name='X-API-KEY'))
) -> Client:
# Check for client in database etc
pass
# repo/app/api/api.py
from fastapi import APIRouter, Security
from app.api.security import get_client
router = APIRouter(..., tags=..., dependencies=[Security(get_client)])
# repo/app/app.py
from app.api.api import router
app = FastAPI()
app.include_router(router, prefix="/api/v1")
How can I patch the get_client
function for my tests in order to have a certain api key for my requests? My tests consist in calling an endpoint using starlette.testclient.TestClient
with the test api key in headers.
# repo/tests/api/routers/test_certain_endpoint.py
from unittest import TestCase
from starlette.testclient import TestClient
async def fake_get_client(client_id):
if client_id == 'my-test-api-key':
return Client(id=client_id)
else:
raise HTTP_401
class TestCertainEndpoint(TestCase):
def test_certain_endpoint(self):
client = TestClient(app=app)
response = client.get('/api/v1/certain/endpoint',
headers={'X-API-KEY': 'my-test-api-key'})
self.assertEqual(response.status_code, 200)
Of course, in this form, my test fails because 'my-test-api-key' key is not in db. And I don't want to be. What I want is to replace get_client
with fake_get_client
at runtime to pass the test.
I considered patching the get_client
function like
@mock.patch('app.api.security.get_client', fake_get_client)
def test_certain_endpoint(self):
...
but this won't work.
Is it possible to patch my get_client
easily in my test, or should I choose another approach?
It's now supported in a recent version :tada:
Here are the new docs: ~https://fastapi.tiangolo.com/tutorial/testing-dependencies/~
Edit: new link: https://fastapi.tiangolo.com/advanced/testing-dependencies/
Make sure to update your FastAPI version before trying it.
I think this should solve your use case, so I'll close this issue now. But feel free to add more comments or create new issues.
The documentation link has changed to: https://fastapi.tiangolo.com/advanced/testing-dependencies/
Most helpful comment
The documentation link has changed to: https://fastapi.tiangolo.com/advanced/testing-dependencies/