pythonasyncioapiasyncfastapiframeworkjsonjson-schemaopenapiopenapi3pydanticpython-typespython3redocreststarletteswaggerswagger-uiuvicornweb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
185 lines
5.9 KiB
185 lines
5.9 KiB
"""
|
|
Tests for the QUERY HTTP method in FastAPI.
|
|
|
|
The QUERY method is a custom HTTP method designed for structured query operations.
|
|
"""
|
|
|
|
import pytest
|
|
from fastapi import APIRouter, FastAPI
|
|
from starlette.testclient import TestClient
|
|
|
|
|
|
class TestQueryHttpMethod:
|
|
"""Tests for the QUERY HTTP method."""
|
|
|
|
@pytest.fixture
|
|
def app(self):
|
|
"""Create a test FastAPI application."""
|
|
app = FastAPI()
|
|
|
|
@app.query("/search")
|
|
def search(q: str, limit: int = 10):
|
|
"""Simple search endpoint using QUERY method."""
|
|
return {
|
|
"query": q,
|
|
"limit": limit,
|
|
"items": [{"id": 1, "name": f"Result for {q}"}],
|
|
}
|
|
|
|
return app
|
|
|
|
def test_query_method_basic(self, app):
|
|
"""Test basic QUERY method request."""
|
|
client = TestClient(app)
|
|
response = client.request("QUERY", "/search?q=python")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["query"] == "python"
|
|
assert data["limit"] == 10
|
|
|
|
def test_query_method_with_params(self, app):
|
|
"""Test QUERY method with multiple parameters."""
|
|
client = TestClient(app)
|
|
response = client.request("QUERY", "/search?q=fastapi&limit=20")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["query"] == "fastapi"
|
|
assert data["limit"] == 20
|
|
|
|
def test_query_method_default_params(self, app):
|
|
"""Test QUERY method uses default parameter values."""
|
|
client = TestClient(app)
|
|
response = client.request("QUERY", "/search?q=default")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["limit"] == 10
|
|
|
|
@pytest.fixture
|
|
def router_app(self):
|
|
"""Test QUERY method with APIRouter."""
|
|
app = FastAPI()
|
|
router = APIRouter()
|
|
|
|
@router.query("/items/search")
|
|
def search_items(name: str, skip: int = 0):
|
|
"""Search for items."""
|
|
return {
|
|
"search_term": name,
|
|
"skip": skip,
|
|
"found_items": [{"id": 1, "name": name}],
|
|
}
|
|
|
|
app.include_router(router)
|
|
return app
|
|
|
|
def test_query_method_with_router(self, router_app):
|
|
"""Test QUERY method with APIRouter."""
|
|
client = TestClient(router_app)
|
|
response = client.request("QUERY", "/items/search?name=widget&skip=5")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["search_term"] == "widget"
|
|
assert data["skip"] == 5
|
|
|
|
@pytest.fixture
|
|
def tagged_app(self):
|
|
"""Test QUERY method with tags and metadata."""
|
|
app = FastAPI()
|
|
|
|
@app.query(
|
|
"/search",
|
|
tags=["search"],
|
|
summary="Search endpoint",
|
|
description="Search for items using QUERY method",
|
|
)
|
|
def search(q: str):
|
|
return {"query": q, "results": []}
|
|
|
|
return app
|
|
|
|
def test_query_method_with_tags(self, tagged_app):
|
|
"""Test QUERY method request succeeds."""
|
|
client = TestClient(tagged_app)
|
|
response = client.request("QUERY", "/search?q=tagged")
|
|
assert response.status_code == 200
|
|
assert response.json()["query"] == "tagged"
|
|
|
|
def test_query_method_openapi_documentation(self, tagged_app):
|
|
"""Test that QUERY method appears in OpenAPI documentation."""
|
|
client = TestClient(tagged_app)
|
|
response = client.get("/openapi.json")
|
|
assert response.status_code == 200
|
|
openapi = response.json()
|
|
assert "/search" in openapi["paths"]
|
|
|
|
@pytest.fixture
|
|
def multiple_query_methods(self):
|
|
"""Test multiple QUERY endpoints."""
|
|
app = FastAPI()
|
|
|
|
@app.query("/users/search")
|
|
def search_users(name: str):
|
|
return {"type": "users", "query": name}
|
|
|
|
@app.query("/posts/search")
|
|
def search_posts(title: str):
|
|
return {"type": "posts", "query": title}
|
|
|
|
return app
|
|
|
|
def test_multiple_query_endpoints(self, multiple_query_methods):
|
|
"""Test multiple QUERY method endpoints."""
|
|
client = TestClient(multiple_query_methods)
|
|
|
|
# Test first endpoint
|
|
response1 = client.request("QUERY", "/users/search?name=alice")
|
|
assert response1.status_code == 200
|
|
assert response1.json()["type"] == "users"
|
|
|
|
# Test second endpoint
|
|
response2 = client.request("QUERY", "/posts/search?title=hello")
|
|
assert response2.status_code == 200
|
|
assert response2.json()["type"] == "posts"
|
|
|
|
|
|
class TestQueryMethodIntegration:
|
|
"""Test integration with FastAPI features."""
|
|
|
|
@pytest.fixture
|
|
def featured_app(self):
|
|
"""App with various FastAPI features."""
|
|
app = FastAPI()
|
|
|
|
@app.query("/search", status_code=200, deprecated=False)
|
|
def search(q: str, limit: int = 10):
|
|
"""Search endpoint with custom config."""
|
|
return {"q": q, "limit": limit}
|
|
|
|
@app.get("/items")
|
|
def list_items():
|
|
"""GET endpoint for comparison."""
|
|
return {"items": []}
|
|
|
|
return app
|
|
|
|
def test_query_and_get_coexist(self, featured_app):
|
|
"""Test that QUERY and GET methods can coexist."""
|
|
client = TestClient(featured_app)
|
|
|
|
# GET should work
|
|
get_response = client.get("/items")
|
|
assert get_response.status_code == 200
|
|
|
|
# QUERY should also work
|
|
query_response = client.request("QUERY", "/search?q=test")
|
|
assert query_response.status_code == 200
|
|
|
|
def test_query_method_with_status_code(self, featured_app):
|
|
"""Test QUERY method respects status_code parameter."""
|
|
client = TestClient(featured_app)
|
|
response = client.request("QUERY", "/search?q=test")
|
|
assert response.status_code == 200
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|
|
|