You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何Mock boto3返回的S3对象列表以完成单元测试?

问题根因
  • 测试代码的Mock配置顺序颠倒:你先执行了bucket.objects.filter(Prefix=S3_PREFIX)才设置返回值,此时被测试函数内部调用filter时还没有拿到预设的返回内容,只会得到默认的空MagicMock对象。
  • 返回值配置逻辑错误:bucket.objects.filter调用后直接返回可迭代对象,不需要二次调用,你设置response.return_value相当于给filter()()的返回值赋值,和实际业务逻辑不匹配。
  • 原业务代码存在笔误:obj.key.endswidth('.zip')应为obj.key.endswith('.zip'),否则即使Mock配置正确,运行时也会抛出AttributeError异常。
修正后的测试代码
from unittest.mock import patch
from dataclasses import dataclass

@dataclass
class MockS3Obj:
    key: str

@patch('module.boto3')
def test_get_files_from_s3(self, mock_boto3):
    # 提前拿到模拟的Bucket对象,在调用被测试函数前完成所有Mock配置
    mock_bucket = mock_boto3.resource.return_value.Bucket.return_value
    # 直接给filter方法设置返回值为可迭代的Mock对象列表
    mock_bucket.objects.filter.return_value = [
        MockS3Obj(key="file.zip"),
        MockS3Obj(key="file.txt"), # 可加入非zip文件验证过滤逻辑有效性
        MockS3Obj(key="test.zip")
    ]
    
    files = module.get_files_from_s3(BUCKET_NAME, S3_PREFIX)
    # 验证过滤结果符合预期
    self.assertEqual(["file.zip", "test.zip"], files)
配置说明
  • 直接通过mock_boto3.resource.return_value.Bucket.return_value获取模拟Bucket对象,不需要手动调用resource和Bucket方法,避免提前触发Mock调用导致配置失效
  • 给mock_bucket.objects.filter.return_value直接赋值列表,列表本身就是可迭代对象,被测试函数遍历时可以正常取出每一个MockS3Obj实例读取key属性
  • 额外加入非zip格式的测试用例,可以同时验证过滤逻辑的正确性,测试覆盖更全面

内容的提问来源于stack exchange,提问作者ezzeddin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 14:36:05