1. ホーム
  2. python

[解決済み] boto3 S3クライアントメソッドをモックする Python

2022-11-13 19:59:01

質問

私はboto3 s3クライアントオブジェクトからsingluarメソッドをモックして、例外をスローしようとしています。しかし、私はこのクラスの他のすべてのメソッドが通常通り動作する必要があります。

を実行してエラーが発生したときに、特異な例外をテストできるようにするためです。 アップロード_パート_コピー

1回目の試行

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()

しかし、これでは以下のようなエラーが発生します。

ImportError: No module named S3

2回目の挑戦

botocore.client.pyのソースコードを見たところ、何か巧妙なことをしていることがわかり、メソッド upload_part_copy が存在しないことがわかりました。を呼び出しているようなことがわかりました。 BaseClient._make_api_call を呼び出すようなので、それをモックにしてみました。

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 メソッドにのみ例外をスローする方法について何かアイデアがありますか?

どのように解決するのですか?

ここに投稿してすぐに、私は解決策を考え出すことができました。ここでは、それが役立つことを願っています:)

import botocore
from botocore.exceptions import ClientError
from mock import patch
import boto3

orig = botocore.client.BaseClient._make_api_call

def mock_make_api_call(self, operation_name, kwarg):
    if operation_name == 'UploadPartCopy':
        parsed_response = {'Error': {'Code': '500', 'Message': 'Error Uploading'}}
        raise ClientError(parsed_response, operation_name)
    return orig(self, operation_name, kwarg)

with patch('botocore.client.BaseClient._make_api_call', new=mock_make_api_call):
    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()

Jordan Philips も素晴らしい解決策を投稿しています。 を使用した を使っています。 クラスを使っています。よりクリーンなソリューションではありますが、特定の操作をモック化することはできませんでした。