首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >模拟boto3 S3客户端方法Python

模拟boto3 S3客户端方法Python
EN

Stack Overflow用户
提问于 2016-05-10 23:59:35
回答 7查看 108.8K关注 0票数 99

我正在尝试模拟boto3 s3客户端对象中的单个方法,以抛出异常。但我需要所有其他方法才能让这个类正常工作。

这样我就可以在执行upload_part_copy时出现错误时测试单个异常测试

第一次尝试

代码语言:javascript
运行
复制
import boto3
from mock import patch

with patch('botocore.client.S3.upload_part_copy', side_effect=Exception('Error Uploading')) as mock:
    client = boto3.client('s3')
    # Should return actual result
    o = client.get_object(Bucket='my-bucket', Key='my-key')
    # Should return mocked exception
    e = client.upload_part_copy()

但是,这会产生以下错误:

代码语言:javascript
运行
复制
ImportError: No module named S3

第二次尝试

在查看了botocore.client.py源代码之后,我发现它做了一些聪明的事情,而upload_part_copy方法并不存在。我发现它似乎调用的是BaseClient._make_api_call,所以我试着模拟一下

代码语言:javascript
运行
复制
import boto3
from mock import patch

with patch('botocore.client.BaseClient._make_api_call', side_effect=Exception('Error Uploading')) as mock:
    client = boto3.client('s3')
    # Should return actual result
    o = client.get_object(Bucket='my-bucket', Key='my-key')
    # Should return mocked exception
    e = client.upload_part_copy()

这抛出了一个异常...但是在我想要避免的get_object上。

关于为什么我只能在upload_part_copy方法上抛出异常,有什么想法吗?

EN

Stack Overflow用户

发布于 2019-04-05 09:51:49

我不得不模拟boto3客户端进行一些集成测试,这有点痛苦!我遇到的问题是moto不能很好地支持KMS,但我不想为S3桶重写自己的mock。所以我创造了所有答案的变形。此外,它在全球范围内工作,这是非常酷的!

我有它与2个文件设置。

第一个是aws_mock.py。对于KMS模拟,我从实时boto3客户端获得了一些预定义的响应。

代码语言:javascript
运行
复制
from unittest.mock import MagicMock

import boto3
from moto import mock_s3

# `create_key` response
create_resp = { ... }

# `generate_data_key` response
generate_resp = { ... }

# `decrypt` response
decrypt_resp = { ... }

def client(*args, **kwargs):
    if args[0] == 's3':
        s3_mock = mock_s3()
        s3_mock.start()
        mock_client = boto3.client(*args, **kwargs)

    else:
        mock_client = boto3.client(*args, **kwargs)

        if args[0] == 'kms':
            mock_client.create_key = MagicMock(return_value=create_resp)
            mock_client.generate_data_key = MagicMock(return_value=generate_resp)
            mock_client.decrypt = MagicMock(return_value=decrypt_resp)

    return mock_client

第二个是实际的测试模块。让我们称它为test_my_module.py。我省略了my_module的代码。以及正在测试的函数。让我们调用这些foobar函数。

代码语言:javascript
运行
复制
from unittest.mock import patch

import aws_mock
import my_module

@patch('my_module.boto3')
def test_my_module(boto3):
    # Some prep work for the mock mode
    boto3.client = aws_mock.client

    conn = boto3.client('s3')
    conn.create_bucket(Bucket='my-bucket')

    # Actual testing
    resp = my_module.foo()
    assert(resp == 'Valid')

    resp = my_module.bar()
    assert(resp != 'Not Valid')

    # Etc, etc, etc...

还有一件事,我不确定这个问题是否得到了解决,但我发现,除非您设置一些环境变量,如凭据和区域,否则moto并不满意。它们不一定是实际的凭据,但需要进行设置。当你读到这篇文章的时候,它可能已经修复了!但这里有一些代码,以防您确实需要它,这一次是shell代码!

代码语言:javascript
运行
复制
export AWS_ACCESS_KEY_ID='foo'
export AWS_SECRET_ACCESS_KEY='bar'
export AWS_DEFAULT_REGION='us-east-1'

我知道它可能不是最漂亮的代码,但是如果你正在寻找一些通用的东西,它应该工作得很好!

票数 4
EN
查看全部 7 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37143597

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档