Skip to content

Commit fe4ff3d

Browse files
committed
add dataclass serializer
1 parent fdde7b9 commit fe4ff3d

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed

tests/functional/idempotency/test_idempotency.py

+110
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
DataRecord,
4141
)
4242
from aws_lambda_powertools.utilities.idempotency.serialization.custom_dict import CustomDictSerializer
43+
from aws_lambda_powertools.utilities.idempotency.serialization.dataclass import DataclassSerializer
4344
from aws_lambda_powertools.utilities.idempotency.serialization.pydantic import PydanticSerializer
4445
from aws_lambda_powertools.utilities.validation import envelopes, validator
4546
from tests.functional.idempotency.utils import (
@@ -1380,6 +1381,115 @@ def collect_payment(payment: PaymentInput) -> dict:
13801381
return PaymentOutput(**payment.dict())
13811382

13821383

1384+
@pytest.mark.parametrize("output_serializer_type", ["explicit", "deduced"])
1385+
def test_idempotent_function_serialization_dataclass(output_serializer_type: str):
1386+
# GIVEN
1387+
dataclasses = get_dataclasses_lib()
1388+
config = IdempotencyConfig(use_local_cache=True)
1389+
mock_event = {"customer_id": "fake", "transaction_id": "fake-id"}
1390+
idempotency_key = f"{TESTS_MODULE_PREFIX}.test_idempotent_function_serialization_dataclass.<locals>.collect_payment#{hash_idempotency_key(mock_event)}" # noqa E501
1391+
persistence_layer = MockPersistenceLayer(expected_idempotency_key=idempotency_key)
1392+
1393+
@dataclasses.dataclass
1394+
class PaymentInput:
1395+
customer_id: str
1396+
transaction_id: str
1397+
1398+
@dataclasses.dataclass
1399+
class PaymentOutput:
1400+
customer_id: str
1401+
transaction_id: str
1402+
1403+
if output_serializer_type == "explicit":
1404+
output_serializer = DataclassSerializer(
1405+
model=PaymentOutput,
1406+
)
1407+
else:
1408+
output_serializer = DataclassSerializer
1409+
1410+
@idempotent_function(
1411+
data_keyword_argument="payment",
1412+
persistence_store=persistence_layer,
1413+
config=config,
1414+
output_serializer=output_serializer,
1415+
)
1416+
def collect_payment(payment: PaymentInput) -> PaymentOutput:
1417+
return PaymentOutput(**dataclasses.asdict(payment))
1418+
1419+
# WHEN
1420+
payment = PaymentInput(**mock_event)
1421+
first_call: PaymentOutput = collect_payment(payment=payment)
1422+
assert first_call.customer_id == payment.customer_id
1423+
assert first_call.transaction_id == payment.transaction_id
1424+
assert isinstance(first_call, PaymentOutput)
1425+
second_call: PaymentOutput = collect_payment(payment=payment)
1426+
assert isinstance(second_call, PaymentOutput)
1427+
assert second_call.customer_id == payment.customer_id
1428+
assert second_call.transaction_id == payment.transaction_id
1429+
1430+
1431+
def test_idempotent_function_serialization_dataclass_failure_no_return_type():
1432+
# GIVEN
1433+
dataclasses = get_dataclasses_lib()
1434+
config = IdempotencyConfig(use_local_cache=True)
1435+
mock_event = {"customer_id": "fake", "transaction_id": "fake-id"}
1436+
idempotency_key = f"{TESTS_MODULE_PREFIX}.test_idempotent_function_serialization_pydantic_failure_no_return_type.<locals>.collect_payment#{hash_idempotency_key(mock_event)}" # noqa E501
1437+
persistence_layer = MockPersistenceLayer(expected_idempotency_key=idempotency_key)
1438+
1439+
@dataclasses.dataclass
1440+
class PaymentInput:
1441+
customer_id: str
1442+
transaction_id: str
1443+
1444+
@dataclasses.dataclass
1445+
class PaymentOutput:
1446+
customer_id: str
1447+
transaction_id: str
1448+
1449+
idempotent_function_decorator = idempotent_function(
1450+
data_keyword_argument="payment",
1451+
persistence_store=persistence_layer,
1452+
config=config,
1453+
output_serializer=DataclassSerializer,
1454+
)
1455+
with pytest.raises(IdempotencyNoSerializationModelError, match="No serialization model was supplied"):
1456+
1457+
@idempotent_function_decorator
1458+
def collect_payment(payment: PaymentInput):
1459+
return PaymentOutput(**payment.dict())
1460+
1461+
1462+
def test_idempotent_function_serialization_dataclass_failure_bad_type():
1463+
# GIVEN
1464+
dataclasses = get_dataclasses_lib()
1465+
config = IdempotencyConfig(use_local_cache=True)
1466+
mock_event = {"customer_id": "fake", "transaction_id": "fake-id"}
1467+
idempotency_key = f"{TESTS_MODULE_PREFIX}.test_idempotent_function_serialization_pydantic_failure_no_return_type.<locals>.collect_payment#{hash_idempotency_key(mock_event)}" # noqa E501
1468+
persistence_layer = MockPersistenceLayer(expected_idempotency_key=idempotency_key)
1469+
1470+
@dataclasses.dataclass
1471+
class PaymentInput:
1472+
customer_id: str
1473+
transaction_id: str
1474+
1475+
@dataclasses.dataclass
1476+
class PaymentOutput:
1477+
customer_id: str
1478+
transaction_id: str
1479+
1480+
idempotent_function_decorator = idempotent_function(
1481+
data_keyword_argument="payment",
1482+
persistence_store=persistence_layer,
1483+
config=config,
1484+
output_serializer=PydanticSerializer,
1485+
)
1486+
with pytest.raises(IdempotencyModelTypeError, match="Model type is not inherited from pydantic BaseModel"):
1487+
1488+
@idempotent_function_decorator
1489+
def collect_payment(payment: PaymentInput) -> dict:
1490+
return PaymentOutput(**payment.dict())
1491+
1492+
13831493
def test_idempotent_function_arbitrary_args_kwargs():
13841494
# Scenario to validate we can use idempotent_function with a function
13851495
# with an arbitrary number of args and kwargs

0 commit comments

Comments
 (0)