mirror of
https://github.com/long2ice/fastapi-cache.git
synced 2026-03-24 20:47:54 +00:00
Decode cache data to the correct endpoint type
Use the return annotation to decode cached data to the correct type. This follows the same logic FastAPI uses to JSON request bodies. For the PickleCoder, this is a no-op as pickle already stores type information in the serialised data.
This commit is contained in:
@@ -1,8 +1,25 @@
|
||||
from typing import Any
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Optional
|
||||
|
||||
import pytest
|
||||
from pydantic import BaseModel, ValidationError
|
||||
|
||||
from fastapi_cache.coder import PickleCoder
|
||||
from fastapi_cache.coder import JsonCoder, PickleCoder
|
||||
|
||||
|
||||
@dataclass
|
||||
class DCItem:
|
||||
name: str
|
||||
price: float
|
||||
description: Optional[str] = None
|
||||
tax: Optional[float] = None
|
||||
|
||||
|
||||
class PDItem(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
description: Optional[str] = None
|
||||
tax: Optional[float] = None
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -13,6 +30,8 @@ from fastapi_cache.coder import PickleCoder
|
||||
(1, 2),
|
||||
[1, 2, 3],
|
||||
{"some_key": 1, "other_key": 2},
|
||||
DCItem(name="foo", price=42.0, description="some dataclass item", tax=0.2),
|
||||
PDItem(name="foo", price=42.0, description="some pydantic item", tax=0.2),
|
||||
],
|
||||
)
|
||||
def test_pickle_coder(value: Any) -> None:
|
||||
@@ -20,3 +39,28 @@ def test_pickle_coder(value: Any) -> None:
|
||||
assert isinstance(encoded_value, str)
|
||||
decoded_value = PickleCoder.decode(encoded_value)
|
||||
assert decoded_value == value
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("value", "return_type"),
|
||||
[
|
||||
(1, None),
|
||||
("some_string", None),
|
||||
((1, 2), tuple[int, int]),
|
||||
([1, 2, 3], None),
|
||||
({"some_key": 1, "other_key": 2}, None),
|
||||
(DCItem(name="foo", price=42.0, description="some dataclass item", tax=0.2), DCItem),
|
||||
(PDItem(name="foo", price=42.0, description="some pydantic item", tax=0.2), PDItem),
|
||||
],
|
||||
)
|
||||
def test_json_coder(value: Any, return_type) -> None:
|
||||
encoded_value = JsonCoder.encode(value)
|
||||
assert isinstance(encoded_value, str)
|
||||
decoded_value = JsonCoder.decode_as_type(encoded_value, type_=return_type)
|
||||
assert decoded_value == value
|
||||
|
||||
|
||||
def test_json_coder_validation_error() -> None:
|
||||
invalid = '{"name": "incomplete"}'
|
||||
with pytest.raises(ValidationError):
|
||||
JsonCoder.decode_as_type(invalid, type_=PDItem)
|
||||
|
||||
@@ -79,3 +79,10 @@ def test_method() -> None:
|
||||
with TestClient(app) as client:
|
||||
response = client.get("/method")
|
||||
assert response.json() == 17
|
||||
|
||||
|
||||
def test_pydantic_model() -> None:
|
||||
with TestClient(app) as client:
|
||||
r1 = client.get("/pydantic_instance").json()
|
||||
r2 = client.get("/pydantic_instance").json()
|
||||
assert r1 == r2
|
||||
|
||||
Reference in New Issue
Block a user