How to mock boto3 S3 upload in Python

Shows how to mock the boto3 S3 client with unit tests and wrap an upload function to return a dictionary with status details.

Medium Python 3.9+ Aug 9, 2026 Cloud + Python 12 views 0 copies

Requires third-party packages — install first
pip install boto3

Python code

29 lines
Python 3.9+
import boto3
from unittest.mock import Mock, patch

class S3Uploader:
    def __init__(self, bucket_name):
        self.bucket_name = bucket_name
        self.s3 = boto3.client("s3", region_name="us-east-1")

    def upload_file(self, local_path, s3_key):
        self.s3.upload_file(local_path, self.bucket_name, s3_key)
        return {"status": "success", "bucket": self.bucket_name, "key": s3_key}

def upload_file_wrapper(uploader, local_path, s3_key):
    result = uploader.upload_file(local_path, s3_key)
    result["uploaded"] = True
    return result

if __name__ == "__main__":
    # Mock boto3 S3 client
    mock_s3 = Mock()
    mock_s3.upload_file.return_value = None

    with patch("boto3.client", return_value=mock_s3):
        uploader = S3Uploader("my-bucket")
        response = upload_file_wrapper(uploader, "file.txt", "folder/file.txt")

    print(response)
    mock_s3.upload_file.assert_called_once_with("file.txt", "my-bucket", "folder/file.txt")
    print("Mock S3 upload verified")

Output

stdout
{'status': 'success', 'bucket': 'my-bucket', 'key': 'folder/file.txt', 'uploaded': True}
Mock S3 upload verified

How it works

The patch context manager replaces boto3.client with a Mock, so no real AWS call is made. The Mock object records calls, allowing assert_called_once_with to verify arguments. The wrapper function augments the original dictionary with an uploaded key. This pattern keeps tests fast, deterministic, and free of network dependencies.

Common mistakes

  • Forgetting to patch before creating the S3 client; the real API is called if patch is applied after instantiation.
  • Not setting `return_value` on the upload method mock, which can cause the wrapper to fail if it expects a dict.
  • Using `patch` without `with` or `start`/`stop`, leaving mocks active in other tests.
  • Asserting with wrong argument order; `upload_file` expects (filename, bucket, key).

Variations

  1. Use `moto` to mock entire S3 API with real behavior for integration testing.
  2. Define a custom fake S3 client class instead of `Mock` for more control.

Real-world use cases

  • Unit testing a deployment script that uploads artifacts to S3 without incurring costs.
  • Verifying that a wrapper function correctly enriches upload metadata before logging or alerting.
  • Simulating S3 failures to test error handling in a backup service.

Sponsored

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Cloud + Python

Related tutorials and quizzes for this topic.