Missing query param `args` when using dependency_overrides
See original GitHub issueFirst check
- I added a very descriptive title to this issue.
- I used the GitHub search to find a similar issue and didn’t find it.
- I searched the FastAPI documentation, with the integrated search.
- I already searched in Google “How to X in FastAPI” and didn’t find any information.
- I already read and followed all the tutorial in the docs and didn’t find an answer.
- I already checked if it is not related to FastAPI but to Pydantic.
- I already checked if it is not related to FastAPI but to Swagger UI.
- I already checked if it is not related to FastAPI but to ReDoc.
- After submitting this, I commit to one of:
- Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.
- I already hit the “watch” button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.
- Implement a Pull Request for a confirmed bug.
Example
Note that this is not a self-contained example (extracting the database code into something others would be able to easily run proved challenging), but hopefully its enough to illustrate the problem:
main.py
from fastapi import Depends, FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session
import database
app = FastAPI()
templates = Jinja2Templates(directory="templates/")
def get_db():
"""Get and manage closure of database."""
db_session = database.get_session()
db = db_session()
try:
yield db
finally:
db.close()
@app.get("/", response_class=HTMLResponse)
async def home(
request: Request,
db: Session = Depends(get_db),
param1="",
param2="",
):
# do stuff
return templates.TemplateResponse(
"home.html",
{
"request": request,
"param1": param1,
"param2": param2,
},
)
conftest.py
import unittest.mock as mock
import pytest
from fastapi.testclient import TestClient
import sqlalchemy
from main import app
@pytest.fixture
def test_app_mock_db():
"""Create a TestClient and mock out the database."""
# Use FASTAPI's mocking framework to replace the get_db dependency with a
# mock
#
# Note that this is implemented on the app object itself and so will persist
# until undone
app.dependency_overrides[main.get_db] = mock.MagicMock(
spec=sqlalchemy.orm.Session
)
with TestClient(app) as client:
yield client
# remove the mock at the end of the test
del app.dependency_overrides[main.get_db]
test_home.py
def test_home(test_app_mock_db):
"""Verify home page is created properly."""
response = test_app_mock_db.get("/")
print(response.json())
assert response.status_code == 200
Description
When attempting to test and endpoint, I’m getting a 422 response and
{'detail': [{'loc': ['query', 'args'], 'msg': 'field required', 'type': 'value_error.missing'}, {'loc': ['query', 'kwargs'], 'msg': 'field required', 'type': 'value_error.missing'}]}
args
is not the name of any of the parameters the endpoint takes, so its unclear why FASTAPI thinks its missing. I’ve been unable to find problems similar to this by searching google with that error information, so it appears that its not common for this to occur.
I have several other endpoints returning TemplateResponse
s for which this problem does not occur (I get HTTP 200 in the tests). It seems to only affect the endpoints which use the database, which I’m attempting to mock in my fixture, and affects the tests for all endpoints which use the database.
I can confirm that get_db
is getting overridden and is not being called (since it throws an error in my test environment), however I do not know why mocking it appears to make FASTAPI expects an args
query parameter.
For kicks and giggles, I’ve tried modifying my test query to provide an args query parameter:
response = test_app_mock_db.get("/?args=True")
which yields the error:
{'detail': [{'loc': ['query', 'kwargs'], 'msg': 'field required', 'type': 'value_error.missing'}]}
If I also pass in kwargs:
response = test_app_mock_db.get("/?args=True&kwargs=True")
I do indeed get a 200 back, but clearly this is incorrect usage since FASTAPI should not expect python’s args/kwargs as query parameters???
What is the proper way to mock out the database calls in this context?
Environment
- OS: Ubuntu
- FastAPI Version: 0.65.0
- Python version: 3.8.5
Issue Analytics
- State:
- Created 2 years ago
- Reactions:9
- Comments:7 (3 by maintainers)
Top GitHub Comments
Try
Instead
The problem of the signature is specific to
MagicMock
, which must be able to be called with any parameters (therefore, the signature is*args, **kwargs
). FastAPI to check the dependencies simply inspect the signature, therefore you get those missing parameters error. Check out the code in FastAPI.A simple solution would be to do something like this:
The main advantage is that you keep a mock as your dependency, therefore you can assert whether it has been called for example.
It works due to the fact that
lambda: None
has an empty signature, and Python mocks support the signature injection after Python 3.8.