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

如何在boto3+moto单元测试中覆盖ClientError异常分支

如何覆盖待办事项脚本中ClientError异常分支的测试

问题背景

我有一个基于模拟AWS基础设施的待办事项Python脚本,其中put_item函数包含ClientError异常处理逻辑,但现有单元测试始终无法覆盖这部分代码:

原脚本中未被覆盖的代码:

except ClientError as e:
    print(e.response['Error']['Message'])

现有测试的核心问题是没有构造出能触发ClientError的场景,导致异常分支从未执行。


解决方案:构造触发ClientError的测试场景

要覆盖该分支,需要让table.put_item()调用抛出ClientError,以下是两种简单可行的实现方式:

方式1:模拟主键冲突(最直接)

通过固定UUID生成值,让两次写入使用同一个主键,触发DynamoDB的主键唯一性约束错误,从而抛出ClientError。

修改测试代码,新增测试用例:

  1. 先导入unittest.mock的patch工具:
from unittest.mock import patch
  1. 添加测试函数:
def test_put_item_duplicate_key_error(self):
    print ('---------------------')
    print ('Start: test_put_item_duplicate_key_error')
    from src.todoList import put_item

    # 固定uuid返回值,确保两次写入用同一个id
    with patch('src.todoList.uuid.uuid1') as mock_uuid:
        mock_uuid.return_value = self.uuid
        # 第一次写入成功
        first_response = put_item(self.text, self.dynamodb)
        self.assertEqual(200, first_response['statusCode'])
        # 第二次写入同一个id,触发主键冲突的ClientError
        second_response = put_item(self.text, self.dynamodb)
        # 异常被捕获后函数无返回值(若原脚本未修改)
        self.assertIsNone(second_response)
    print ('End: test_put_item_duplicate_key_error')

方式2:操作不存在的表

临时修改环境变量,让get_table指向一个未创建的表,触发ResourceNotFoundException(属于ClientError子类)。

新增测试用例:

def test_put_item_nonexistent_table(self):
    print ('---------------------')
    print ('Start: test_put_item_nonexistent_table')
    from src.todoList import put_item

    # 临时替换环境变量中的表名
    original_table = os.environ.get('DYNAMODB_TABLE')
    os.environ['DYNAMODB_TABLE'] = 'non-existent-todo-table'
    
    try:
        response = put_item(self.text, self.dynamodb)
        self.assertIsNone(response)
    finally:
        # 恢复原环境变量,避免影响其他测试
        if original_table:
            os.environ['DYNAMODB_TABLE'] = original_table
        else:
            del os.environ['DYNAMODB_TABLE']
    print ('End: test_put_item_nonexistent_table')

现有测试的修正提示

你当前的test_put_todo_error用例写法错误:

self.assertRaises(Exception, put_item("", self.dynamodb))

该代码会直接执行put_item,而非传递可调用对象给assertRaises,正确写法应为:

self.assertRaises(Exception, put_item, "", self.dynamodb)

但注意:原脚本中put_item已经捕获了ClientError,不会向外抛出异常,所以这个测试的逻辑本身不成立,建议删除或调整为验证异常分支的行为(比如验证错误日志输出)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 23:37:02