Fastapi: [QUESTION] How can I mock/patch a router dependency?

Created on 6 Jun 2019  路  3Comments  路  Source: tiangolo/fastapi

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?

question

Most helpful comment

The documentation link has changed to: https://fastapi.tiangolo.com/advanced/testing-dependencies/

All 3 comments

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/

Was this page helpful?
0 / 5 - 0 ratings