Skip to content

Commit b0d6665

Browse files
author
Tom McCarthy
committed
docs: add "testing your code" section to the idempotency docs
1 parent 62a98f2 commit b0d6665

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed

docs/utilities/idempotency.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,123 @@ The idempotency utility can be used with the `validator` decorator. Ensure that
765765
!!! tip "JMESPath Powertools functions are also available"
766766
Built-in functions known in the validation utility like `powertools_json`, `powertools_base64`, `powertools_base64_gzip` are also available to use in this utility.
767767

768+
769+
## Testing your code
770+
771+
The idempotency utility provides several routes to test your code.
772+
773+
### Disabling the idempotency utility
774+
When testing your code, you may wish to disable the idempotency logic altogether and focus on testing your business logic. To do this, you can set the environment variable `POWERTOOLS_IDEMPOTENCY_DISABLED`
775+
with a truthy value. If you prefer setting this for specific tests, and are using Pytest, you can use [monkeypatch](https://docs.pytest.org/en/latest/monkeypatch.html) fixture:
776+
777+
=== "tests.py"
778+
779+
```python hl_lines="2 3"
780+
def test_idempotent_lambda_handler(monkeypatch):
781+
# Set POWERTOOLS_IDEMPOTENCY_DISABLED before calling decorated functions
782+
monkeypatch.setenv("POWERTOOLS_IDEMPOTENCY_DISABLED", 1)
783+
784+
result = handler()
785+
...
786+
```
787+
=== "app.py"
788+
789+
```python
790+
from aws_lambda_powertools.utilities.idempotency import (
791+
DynamoDBPersistenceLayer, idempotent
792+
)
793+
794+
persistence_layer = DynamoDBPersistenceLayer(table_name="idempotency")
795+
796+
@idempotent(persistence_store=persistence_layer)
797+
def handler(event, context):
798+
print('expensive operation')
799+
return {
800+
"payment_id": 12345,
801+
"message": "success",
802+
"statusCode": 200,
803+
}
804+
```
805+
806+
### Testing with DynamoDB Local
807+
808+
To test with DynamoDB local, you can replace the `Table` resource used by the persistence layer with one you create inside your tests. This allows you to set the endpoint_url.
809+
810+
=== "tests.py"
811+
812+
```python hl_lines="6 7 8"
813+
import boto3
814+
815+
import app
816+
817+
# Create our own Table resource using the endpoint for our DynamoDB Local instance
818+
resource = boto3.resource("dynamodb", endpoint_url='http://localhost:8000')
819+
table = resource.Table(app.persistence_layer.table_name)
820+
app.persistence_layer.table = table
821+
822+
def test_idempotent_lambda():
823+
result = app.handler({'testkey': 'testvalue'}, {})
824+
assert result['payment_id'] == 12345
825+
```
826+
827+
=== "app.py"
828+
829+
```python
830+
from aws_lambda_powertools.utilities.idempotency import (
831+
DynamoDBPersistenceLayer, idempotent
832+
)
833+
834+
persistence_layer = DynamoDBPersistenceLayer(table_name="idempotency")
835+
836+
@idempotent(persistence_store=persistence_layer)
837+
def handler(event, context):
838+
print('expensive operation')
839+
return {
840+
"payment_id": 12345,
841+
"message": "success",
842+
"statusCode": 200,
843+
}
844+
```
845+
846+
### How do I mock all DynamoDB I/O operations
847+
848+
The idempotency utility lazily creates the dynamodb [Table](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table) which it uses to access DynamoDB.
849+
This means it is possible to pass a mocked Table resource, or stub various methods.
850+
851+
=== "tests.py"
852+
853+
```python hl_lines="6 7 8 9"
854+
from unittest.mock import MagicMock
855+
856+
import app
857+
858+
def test_idempotent_lambda():
859+
table = MagicMock()
860+
app.persistence_layer.table = table
861+
result = app.handler({'testkey': 'testvalue'}, {})
862+
table.put_item.assert_called()
863+
...
864+
```
865+
866+
=== "app.py"
867+
868+
```python
869+
from aws_lambda_powertools.utilities.idempotency import (
870+
DynamoDBPersistenceLayer, idempotent
871+
)
872+
873+
persistence_layer = DynamoDBPersistenceLayer(table_name="idempotency")
874+
875+
@idempotent(persistence_store=persistence_layer)
876+
def handler(event, context):
877+
print('expensive operation')
878+
return {
879+
"payment_id": 12345,
880+
"message": "success",
881+
"statusCode": 200,
882+
}
883+
```
884+
768885
## Extra resources
769886

770887
If you're interested in a deep dive on how Amazon uses idempotency when building our APIs, check out

0 commit comments

Comments
 (0)