Skip to content

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_s3mock_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_s3from moto import mock_aws
コンテキストマネージャwith mock_s3():with mock_aws():
モック対象S3サービスのみ全AWSサービス

変更の背景

moto 5.0では全てのサービス固有デコレータがmock_awsに統合されました。これにより:

  1. 複数サービスをまたぐテストコードの簡素化
  2. デコレータ管理の一元化
  3. 新サービス追加時の互換性維持

が実現されています。変更の詳細は公式変更履歴で確認できます。

互換性維持の方法

既存コードをすぐに更新できない場合は、バージョンを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'  # 必須