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

模拟AWS资源抛出ClientError时DynamoDB单元测试失效问题求解

问题原因
  • 第一,Stubber绑定的客户端实例不匹配。你在测试类setUp中初始化的self.dynamodb资源实例,和foo.py的update_table函数内部重新调用boto3.resource('dynamodb')生成的资源实例是两个完全独立的对象,你给前者客户端绑定的Stubber完全不会作用到后者的调用上。
  • 第二,@mock_dynamodb2装饰器优先级高于Stubber。moto提供的这个装饰器会全局接管所有boto3的DynamoDB请求,所有相关操作都会直接走moto的模拟实现,不会触发你手动添加的Stubber错误。
解决方案

这里提供两种可行的实现方式:

方案1:使用Stubber模拟,移除moto的DynamoDB mock

不需要依赖moto的模拟表,直接通过Stubber绑定调用错误,修改点如下:

  1. 去掉测试类上的@mock_dynamodb2装饰器,删除setUp中创建模拟表的相关代码(Stubber不需要真实模拟表存在)
  2. 调整测试逻辑让Stubber作用到被测函数内部生成的dynamodb实例上,参考代码:
import boto3
import botocore
from botocore.stub import Stubber
import foo
import unittest
from unittest import mock

class TestUpdateTable(unittest.TestCase):
    def test_returns_none(self):
        stubber = None
        original_resource = boto3.resource

        def mock_resource(service):
            nonlocal stubber
            if service == 'dynamodb':
                dynamodb = original_resource('dynamodb')
                stubber = Stubber(dynamodb.meta.client)
                stubber.add_client_error('update_item')
                stubber.activate()
                return dynamodb
            return original_resource(service)
        
        with mock.patch('foo.boto3.resource', side_effect=mock_resource):
            response = foo.update_table("123")
            stubber.deactivate()
            self.assertIsNone(response)

方案2:保留moto mock,直接mock update_item方法抛出异常

如果你需要保留moto的DynamoDB模拟做其他测试,可以直接模拟Table对象的update_item方法抛出ClientError,代码更简洁:

# 保留原测试类的@mock_dynamodb2装饰器和setUp代码
def test_returns_none(self):
    with mock.patch('foo.boto3.resource') as mock_resource:
        # 配置mock的table对象的update_item方法抛出ClientError
        mock_table = mock_resource.return_value.Table.return_value
        mock_table.update_item.side_effect = botocore.exceptions.ClientError(
            {'Error': {'Code': 'InternalError', 'Message': 'DynamoDB internal error'}},
            'UpdateItem'
        )
        response = foo.update_table("123")
        self.assertIsNone(response)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 18:24:10