Skip to content

Missing query param args when using dependency_overrides #3331

@ascended121

Description

@ascended121

First 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 TemplateResponses 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions