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.
171 lines
5.3 KiB
171 lines
5.3 KiB
import pytest
|
|
from fastapi import APIRouter, FastAPI
|
|
from fastapi.testclient import TestClient
|
|
from pydantic import BaseModel
|
|
|
|
from .utils import needs_pydanticv1, needs_pydanticv2
|
|
|
|
|
|
@needs_pydanticv2
|
|
@pytest.mark.parametrize(
|
|
"include_error_input,include_error_url",
|
|
[(False, False), (False, True), (True, False), (True, True)],
|
|
)
|
|
def test_input_and_url_fields_with_pydanticv2(include_error_input, include_error_url):
|
|
app = FastAPI(
|
|
include_error_input=include_error_input, include_error_url=include_error_url
|
|
)
|
|
|
|
@app.get("/get1/{path_param}")
|
|
def get1(path_param: int): ...
|
|
|
|
@app.get("/get2/")
|
|
def get2(query_param: int): ...
|
|
|
|
class Body1(BaseModel): ...
|
|
|
|
class Body2(BaseModel): ...
|
|
|
|
@app.post("/post1/")
|
|
def post1(body1: Body1, body2: Body2): ...
|
|
|
|
router = APIRouter(
|
|
include_error_input=include_error_input, include_error_url=include_error_url
|
|
)
|
|
|
|
@router.get("/get3/{path_param}")
|
|
def get3(path_param: int): ...
|
|
|
|
@router.get("/get4/")
|
|
def get4(query_param: int): ...
|
|
|
|
@router.post("/post2/")
|
|
def post2(body1: Body1, body2: Body2): ...
|
|
|
|
app.include_router(router)
|
|
client = TestClient(app)
|
|
with client:
|
|
invalid = "not-an-integer"
|
|
|
|
for path in ["get1", "get3"]:
|
|
response = client.get(f"/{path}/{invalid}")
|
|
assert response.status_code == 422, response.text
|
|
error = response.json()["detail"][0]
|
|
if include_error_input:
|
|
assert error["input"] == invalid
|
|
else:
|
|
assert "input" not in error
|
|
if include_error_url:
|
|
assert "url" in error
|
|
else:
|
|
assert "url" not in error
|
|
|
|
for path in ["get2", "get4"]:
|
|
response = client.get(f"/{path}/")
|
|
assert response.status_code == 422, response.text
|
|
error = response.json()["detail"][0]
|
|
if include_error_input:
|
|
assert error["type"] == "missing"
|
|
assert error["input"] is None
|
|
else:
|
|
assert "input" not in error
|
|
if include_error_url:
|
|
assert "url" in error
|
|
else:
|
|
assert "url" not in error
|
|
|
|
response = client.get(f"/{path}/?query_param={invalid}")
|
|
assert response.status_code == 422, response.text
|
|
error = response.json()["detail"][0]
|
|
if include_error_input:
|
|
assert error["input"] == invalid
|
|
else:
|
|
assert "input" not in error
|
|
if include_error_url:
|
|
assert "url" in error
|
|
else:
|
|
assert "url" not in error
|
|
|
|
for path in ["post1", "post2"]:
|
|
response = client.post(f"/{path}/", json=["not-a-dict"])
|
|
assert response.status_code == 422
|
|
error = response.json()["detail"][0]
|
|
if include_error_input:
|
|
assert error["type"] == "missing"
|
|
assert error["input"] is None
|
|
else:
|
|
assert "input" not in error
|
|
if include_error_url:
|
|
assert "url" in error
|
|
else:
|
|
assert "url" not in error
|
|
|
|
|
|
# TODO: remove when deprecating Pydantic v1
|
|
@needs_pydanticv1
|
|
@pytest.mark.parametrize(
|
|
"include_error_input,include_error_url",
|
|
[(False, False), (False, True), (True, False), (True, True)],
|
|
)
|
|
def test_input_and_url_fields_with_pydanticv1(include_error_input, include_error_url):
|
|
app = FastAPI(
|
|
include_error_input=include_error_input, include_error_url=include_error_url
|
|
)
|
|
|
|
@app.get("/get1/{path_param}")
|
|
def get1(path_param: int): ...
|
|
|
|
@app.get("/get2/")
|
|
def get2(query_param: int): ...
|
|
|
|
class Body1(BaseModel): ...
|
|
|
|
class Body2(BaseModel): ...
|
|
|
|
@app.post("/post1/")
|
|
def post1(body1: Body1, body2: Body2): ...
|
|
|
|
router = APIRouter(
|
|
include_error_input=include_error_input, include_error_url=include_error_url
|
|
)
|
|
|
|
@router.get("/get3/{path_param}")
|
|
def get3(path_param: int): ...
|
|
|
|
@router.get("/get4/")
|
|
def get4(query_param: int): ...
|
|
|
|
@router.post("/post2/")
|
|
def post2(body1: Body1, body2: Body2): ...
|
|
|
|
app.include_router(router)
|
|
client = TestClient(app)
|
|
with client:
|
|
invalid = "not-an-integer"
|
|
|
|
for path in ["get1", "get3"]:
|
|
response = client.get(f"/{path}/{invalid}")
|
|
assert response.status_code == 422, response.text
|
|
error = response.json()["detail"][0]
|
|
assert "input" not in error
|
|
assert "url" not in error
|
|
|
|
for path in ["get2", "get4"]:
|
|
response = client.get(f"/{path}/")
|
|
assert response.status_code == 422, response.text
|
|
error = response.json()["detail"][0]
|
|
assert "input" not in error
|
|
assert "url" not in error
|
|
|
|
response = client.get(f"/{path}/?query_param={invalid}")
|
|
assert response.status_code == 422, response.text
|
|
error = response.json()["detail"][0]
|
|
assert "input" not in error
|
|
assert "url" not in error
|
|
|
|
for path in ["post1", "post2"]:
|
|
response = client.post(f"/{path}/", json=["not-a-dict"])
|
|
assert response.status_code == 422
|
|
error = response.json()["detail"][0]
|
|
assert "input" not in error
|
|
assert "url" not in error
|
|
|