LoginSignup
2
3

More than 3 years have passed since last update.

pythonでS3をモック化できるStubberを使って単体テスト

Last updated at Posted at 2021-04-20

記事について

pythonでS3をモック化する際に、以前はpython標準のMockを使っていたけど、boto3に標準のStubberという便利なモジュールが用意されているので、使用してみた。

なお、コードは、実際に動かしたものを公開用に修正したもので、動作確認はしておりません。ご了承ください。

環境

  • python3系
  • boto3

テストコードを書いてみる

S3からオブジェクトをGETする

対象コード

import boto3
    func_get():
        s3 = boto3.resource('s3')
        bucket = 'bucket'
        key = '/key/object.json'
        obj = s3.Object(bucket, key)

        res = obj.get()

        return res

テストコード

正常系

from botocore.stub import Stubber
from botocore.exceptions import ClientError
from unittest import TestCase
from unittest import mock
import boto3
import contextlib

class TestGetGehirnFiles(TestCase):
    def test_get_files_OK(self):
        s3 = boto3.resource('s3')
        stubber = Stubber(s3.meta.client)
        # Bodyの中:botocore.response.StreamingBody = ファイルストリーム
        body = open('./test_body.json')
        res = {"ResponseMetadata": {"HTTPStatusCode": 200}, 'Body': body}
        stubber.add_response('get_object', res)
        stubber.activate()

        # ここではcontextlibで書いてるけど、Mock対象が一つの場合にはcontextlibを使用する必要はない。
        with contextlib.ExitStack() as stack:
            stack.enter_context(mock.patch('boto3.resource', return_value=s3))


            ex_body = open('./test_body.json')
            expectation = {"ResponseMetadata": {"HTTPStatusCode": 200}, 'Body': ex_body}

            res = func_get()

            self.assertDictEqual(expectation, res)
            body.close()
            ex_body.close()

異常系

例外を返す
- body = open('./test_body.json')
- res = {"ResponseMetadata": {"HTTPStatusCode": 200}, 'Body': body}
- stubber.add_response('get_object', res)

+ stubber.add_client_error('get_object', service_error_code='AccessDenied')

複数回の呼び出しのレスポンスを定義する場合

ファーストインファーストアウトで定義できるので、例えば、例外を2回返した後に正常レスポンスを返す場合、以下のように記載する

s3 = boto3.resource('s3')
stubber = Stubber(s3.meta.client)
stubber.add_client_error('get_object', service_error_code='AccessDenied')
stubber.add_client_error('get_object', service_error_code='AccessDenied')
stubber.add_response('get_object', xxx)
stubber.activate()

S3にオブジェクトをPUTする

基本的にGetと同じなので、省略。以下だけ変更すれば良い

- stubber.add_response('get_object', res)
+ stubber.add_response('put_object', res)

参考ページ

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3