Mocking boto3 S3 client method Python Mocking boto3 S3 client method Python python python

Mocking boto3 S3 client method Python


Botocore has a client stubber you can use for just this purpose: docs.

Here's an example of putting an error in:

import boto3from botocore.stub import Stubberclient = boto3.client('s3')stubber = Stubber(client)stubber.add_client_error('upload_part_copy')stubber.activate()# Will raise a ClientErrorclient.upload_part_copy()

Here's an example of putting a normal response in. Additionally, the stubber can now be used in a context. It's important to note that the stubber will verify, so far as it is able, that your provided response matches what the service will actually return. This isn't perfect, but it will protect you from inserting total nonsense responses.

import boto3from botocore.stub import Stubberclient = boto3.client('s3')stubber = Stubber(client)list_buckets_response = {    "Owner": {        "DisplayName": "name",        "ID": "EXAMPLE123"    },    "Buckets": [{        "CreationDate": "2016-05-25T16:55:48.000Z",        "Name": "foo"    }]}expected_params = {}stubber.add_response('list_buckets', list_buckets_response, expected_params)with stubber:    response = client.list_buckets()assert response == list_buckets_response


As soon as I posted on here I managed to come up with a solution. Here it is hope it helps :)

import botocorefrom botocore.exceptions import ClientErrorfrom mock import patchimport boto3orig = botocore.client.BaseClient._make_api_calldef mock_make_api_call(self, operation_name, kwarg):    if operation_name == 'UploadPartCopy':        parsed_response = {'Error': {'Code': '500', 'Message': 'Error Uploading'}}        raise ClientError(parsed_response, operation_name)    return orig(self, operation_name, kwarg)with patch('botocore.client.BaseClient._make_api_call', new=mock_make_api_call):    client = boto3.client('s3')    # Should return actual result    o = client.get_object(Bucket='my-bucket', Key='my-key')    # Should return mocked exception    e = client.upload_part_copy()

Jordan Philips also posted a great solution using the the botocore.stub.Stubber class. Whilst a cleaner solution I was un-able to mock specific operations.


Here's an example of a simple python unittest that can be used to fake client = boto3.client('ec2') api call...

import boto3 class MyAWSModule():    def __init__(self):        client = boto3.client('ec2')        tags = client.describe_tags(DryRun=False)class TestMyAWSModule(unittest.TestCase):    @mock.patch("boto3.client.get_tags")    @mock.patch("boto3.client")    def test_open_file_with_existing_file(self, mock_boto_client, mock_describe_tags):        mock_describe_tags.return_value = mock_get_tags_response        my_aws_module = MyAWSModule()        mock_boto_client.assert_call_once('ec2')        mock_describe_tags.assert_call_once_with(DryRun=False)mock_get_tags_response = {    'Tags': [        {            'ResourceId': 'string',            'ResourceType': 'customer-gateway',            'Key': 'string',            'Value': 'string'        },    ],'NextToken': 'string'}

hopefully that helps.