moto 5.0におけるmock_s3のインポートエラー
問題の説明
PythonテストコードでAWSのモック作成にmoto
ライブラリを使用する際、以下のエラーが発生します:
python
ImportError: cannot import name 'mock_s3' from 'moto'
具体的には、次のようなテストフィクスチャコードでエラーが発生します:
python
import pytest
from moto import mock_s3 # ここでImportErrorが発生
@pytest.fixture(scope='module')
def s3():
with mock_s3():
os.environ['AWS_ACCESS_KEY_ID'] = 'test'
os.environ['AWS_SECRET_ACCESS_KEY'] = 'test'
os.environ['AWS_DEFAULT_REGION'] = 'us-east-1'
s3 = boto3.resource('s3')
s3.create_bucket(Bucket='test_bucket')
yield s3
このエラーはmoto 5.0へのバージョンアップが原因です。以前のバージョン(4.x系)では動作していたコードが、最新バージョンで互換性が失われています。
エラー発生条件
moto
ライブラリをバージョン5.0以上にアップグレード後- 従来の
mock_s3
やmock_ec2
などのサービス固有デコレータを使用しているコード
解決方法
正しいインポート方法への変更
mock_s3
の代わりに**mock_aws
をインポート**し、コンテキストマネージャとして使用します:
python
import pytest
from moto import mock_aws # mock_s3 から変更
@pytest.fixture(scope='module')
def s3():
with mock_aws(): # コンテキストマネージャ名を変更
os.environ['AWS_ACCESS_KEY_ID'] = 'test'
os.environ['AWS_SECRET_ACCESS_KEY'] = 'test'
os.environ['AWS_DEFAULT_REGION'] = 'us-east-1'
s3 = boto3.resource('s3')
s3.create_bucket(Bucket='test_bucket')
yield s3
主な変更点
要素 | 旧バージョン (4.x) | 新バージョン (5.0+) |
---|---|---|
インポート | from moto import mock_s3 | from moto import mock_aws |
コンテキストマネージャ | with mock_s3(): | with mock_aws(): |
モック対象 | S3サービスのみ | 全AWSサービス |
変更の背景
moto 5.0では全てのサービス固有デコレータがmock_aws
に統合されました。これにより:
- 複数サービスをまたぐテストコードの簡素化
- デコレータ管理の一元化
- 新サービス追加時の互換性維持
が実現されています。変更の詳細は公式変更履歴で確認できます。
互換性維持の方法
既存コードをすぐに更新できない場合は、バージョンを4.x系に固定:
bash
pip install 'moto<5.0'
ただし、新機能やセキュリティ修正は5.x系で提供されるため、早期の移行を推奨します。
完全な修正コード例
python
import os
import boto3
import pytest
from moto import mock_aws # 修正ポイント
@pytest.fixture(scope="module")
def aws_credentials():
"""AWS認証情報のモック設定"""
os.environ["AWS_ACCESS_KEY_ID"] = "testing"
os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
os.environ["AWS_DEFAULT_REGION"] = "us-east-1"
@pytest.fixture(scope="module")
def s3_client(aws_credentials):
"""S3クライアントのフィクスチャ"""
with mock_aws(): # 修正ポイント
conn = boto3.client("s3")
conn.create_bucket(Bucket="test-bucket")
yield conn
def test_s3_upload(s3_client):
"""バケット存在確認テスト"""
buckets = s3_client.list_buckets()["Buckets"]
assert buckets[0]["Name"] == "test-bucket"
よくある質問
Q: 複数サービスを同時にモックできますか?
A: はい。mock_aws
は全てのAWSサービスを自動でモックします:
python
# EC2とS3を同時にモック
with mock_aws():
ec2 = boto3.client('ec2')
s3 = boto3.client('s3')
Q: リージョン指定は必要ですか?
A: 必要です。motoはデフォルトリージョンを持たないため、環境変数か明示的な指定が必須:
python
os.environ['AWS_DEFAULT_REGION'] = 'ap-northeast-1' # 必須