Mocking Boto3 with pytest
Posted 25 July 2023
When writing unit tests that interact with AWS services like S3 or DynamoDB using the boto3 Python library you'll want to mock those requests. You can use the botocore Stubber to achieve this.
Given a function that queries DynamoDB for an item:
import boto3
def get_item(id):
dynamodb = boto3.client("dynamodb")
response = dynamodb.get_item(
TableName="item_table",
Key={"id": id}
)
return response.get("Item")
You can write a pytest unit test using botocore.stub
to mock the requests:
import boto3
from botocore.stub import Stubber
from my_project import get_item
def test_get_item(mocker):
dynamodb = boto3.client("dynamodb")
stubber = Stubber(dynamodb)
stubber.add_response(
"get_item",
{"hello": "world"},
{"TableName": "item_table", "Key": {"id": "hello-world"}}
)
with mocker.patch(
"boto3.client", return_value=dynamodb
):
with stubber:
result = get_item("hello-world")
assert result["hello"] == "world"
- The
add_response
call adds a mock response of{"hello": "world"}
for aget_item
call, as well as asserting the expected arguments given with stubber:
activates the Stubber - you can also callstubber.activate()
after setting up mock responses
You can also use the stubber with the boto3.resource
API:
import boto3
def get_item(id):
dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("item_table")
response = table.get_item(
Key={"id": id}
)
return response.get("Item")
import boto3
from botocore.stub import Stubber
from my_project import get_item
def test_get_item(mocker):
dynamodb = boto3.resource("dynamodb")
stubber = Stubber(dynamodb.meta.client) # Access the client through `meta`
stubber.add_response(
"get_item",
{"hello": "world"},
{"TableName": "item_table", "Key": {"id": "hello-world"}}
)
with mocker.patch(
"boto3.resource", return_value=dynamodb
):
with stubber:
result = get_item("hello-world")
assert result["hello"] == "world"