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

如何用botocore Stubber测试调用boto3 resource的Python函数

解决boto3 Resource结合Stubber单元测试时的UnStubbedResponseError问题

问题场景

使用boto3 Resource编写了simpleput函数,尝试用botocore Stubber编写单元测试时,出现错误:

botocore.exceptions.UnStubbedResponseError: Error getting response stub for operation PutObject: Unexpected API Call: A call was made but no additional calls expected. Either the API Call was not stubbed or it was called multiple times.

不清楚如何正确注入/拦截目标函数的S3调用。

业务代码(simpleput.py)

s3 = boto3.resource('s3')

def simpleput(bucket: str, filename: str):
    s3bucket = s3.Bucket(bucket)
    s3.Object(bucket, filename).put(Body='one\ntwo')

问题分析

测试代码存在两个核心问题:

  • 在with stubber块内手动调用了client.put_object,提前消耗了唯一的桩化响应,导致后续被测函数调用PutObject时无桩可用
  • 冗余调用导致桩化次数不匹配,触发未预期调用的错误

修正后的测试代码

import unittest
import boto3
from botocore.stub import Stubber
import simpleput


class TestModule(unittest.TestCase):
    def test_seed(self):
        # 创建带桩的S3资源实例
        s3_resource = boto3.resource('s3')
        client = s3_resource.meta.client
        stubber = Stubber(client)
        
        # 替换被测模块中的全局s3实例
        simpleput.s3 = s3_resource

        # 定义桩化响应和预期参数
        response = {"Expiration": "whatever", "ETag": "12345", "VersionId": "1.0"}
        expected_params = {
            "Body": 'one\ntwo',
            "Bucket": 'mybucket',
            "Key": 'mykey',
        }
        stubber.add_response('put_object', response, expected_params)

        # 在桩上下文内执行被测函数
        with stubber:
            simpleput.simpleput('mybucket', 'mykey')
            
            # 验证所有桩化调用都已被触发
            stubber.assert_no_pending_responses()

关键修正点

  • 移除了手动调用的client.put_object,避免提前消耗桩化响应
  • 使用stubber.assert_no_pending_responses()确保被测函数触发了预期的API调用
  • 确保被测模块使用的是我们创建的带桩的S3资源实例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 19:18:19