How to mock boto3 S3 upload file wrapper in Python
Wrap an S3 put_object call in a testable function that returns metadata, and mock boto3 to verify the upload without touching AWS.
pip install boto3
Python code
28 linesimport boto3
import io
def upload_file_to_s3(file_obj, bucket, key, object_metadata=None):
"""Upload a file-like object to S3 and return a metadata dict."""
s3 = boto3.client("s3")
content = file_obj.read()
s3.put_object(
Bucket=bucket,
Key=key,
Body=content,
Metadata=object_metadata or {},
)
return {
"bucket": bucket,
"key": key,
"size_bytes": len(content),
"content_type": "application/octet-stream",
}
if __name__ == "__main__":
# Simulate upload with an in-memory file
file_data = b"Hello, S3 upload wrapper!"
mem_file = io.BytesIO(file_data)
result = upload_file_to_s3(mem_file, "my-bucket", "path/to/hello.txt")
print(result)
Output
{'bucket': 'my-bucket', 'key': 'path/to/hello.txt', 'size_bytes': 25, 'content_type': 'application/octet-stream'}
How it works
The function reads the whole file-like object into memory, then calls put_object with the bucket, key, body, and optional metadata. It returns a clean dict with the bucket, key, byte size, and a fixed content type, which makes assertions easy in tests. To mock, patch boto3.client and check that put_object was called with the expected arguments. Keeping the AWS call inside one wrapper makes the rest of your code trivial to unit test without network access.
Common mistakes
- Calling boto3.client("s3") inside the wrapper makes patching trickier — mock boto3.client directly
- Forgetting to reset BytesIO pointer if the file object is reused after reading
- Assuming put_object returns useful data — the return dict is your own contract
Variations
- Use s3.upload_fileobj(file_obj, bucket, key) for streaming large files instead of reading all bytes
- Return the actual put_object response merged with your metadata when you need ETag or VersionId
Real-world use cases
- Unit-testing file upload logic in a Flask or FastAPI endpoint without provisioning S3 in CI.
- Verifying that a backup script writes the correct object key and metadata before a real deploy.
- Building a reusable service layer so multiple Lambda functions share one tested S3 upload path.
Sponsored
More from Cloud + Python
- Build a URL Shortener Client with Python medium
- Create a Cloud Storage Helper Class in Python easy
- Create a Data Helper Class for Beginners in Python easy
- Cross Account Role Chaining Mock Credentials in Python medium
- Exponential Backoff with Jitter for Cloud API Calls in Python medium
- Generate Mock CloudFormation Stack Events in Python easy
Keep learning
Related tutorials and quizzes for this topic.