{"id":659,"library":"moto","title":"Moto","description":"Moto is a Python library that allows developers to easily mock AWS services for testing purposes. It intercepts Boto3 calls and routes them to an in-memory mock, simulating AWS API behavior locally without actual AWS interaction. The current version is 5.1.22, and it typically sees new releases every 1-2 weeks, ensuring continuous updates for AWS service support.","status":"active","version":"5.1.22","language":"python","source_language":"en","source_url":"https://github.com/getmoto/moto","tags":["aws","mocking","testing","boto3","unit-testing"],"install":[{"cmd":"pip install moto[all]","lang":"bash","label":"Install with all service mocks"},{"cmd":"pip install 'moto[s3,dynamodb]'","lang":"bash","label":"Install specific service mocks (e.g., S3, DynamoDB)"}],"dependencies":[{"reason":"Moto intercepts calls made by boto3, the AWS SDK for Python.","package":"boto3","optional":false},{"reason":"Requires Python 3.9 or higher.","package":"python","optional":false},{"reason":"Various service-specific dependencies are installed via extras (e.g., moto[s3], moto[ec2]) or moto[all].","package":"moto[service_name]","optional":true}],"imports":[{"note":"As of Moto v5.x, service-specific decorators like `mock_s3` or `mock_dynamodb` have been replaced by the single, unified `mock_aws` decorator.","wrong":"from moto import mock_s3","symbol":"mock_aws","correct":"from moto import mock_aws"}],"quickstart":{"code":"import boto3\nfrom moto import mock_aws\nimport os\n\n@mock_aws\ndef test_s3_bucket_creation():\n    # Ensure dummy AWS credentials are set for botocore to not attempt real calls\n    os.environ['AWS_ACCESS_KEY_ID'] = 'testing'\n    os.environ['AWS_SECRET_ACCESS_KEY'] = 'testing'\n    os.environ['AWS_SECURITY_TOKEN'] = 'testing'\n    os.environ['AWS_SESSION_TOKEN'] = 'testing'\n    os.environ['AWS_DEFAULT_REGION'] = 'us-east-1'\n\n    s3_client = boto3.client('s3', region_name='us-east-1')\n    bucket_name = 'my-test-bucket-123'\n    \n    # Create a bucket in the mocked AWS environment\n    s3_client.create_bucket(Bucket=bucket_name)\n    \n    # List buckets and verify the new bucket exists\n    response = s3_client.list_buckets()\n    buckets = [b['Name'] for b in response['Buckets']]\n    \n    assert bucket_name in buckets\n    print(f\"Successfully created and verified bucket: {bucket_name}\")\n\nif __name__ == '__main__':\n    test_s3_bucket_creation()","lang":"python","description":"This quickstart demonstrates how to mock an S3 service using the `@mock_aws` decorator. It creates a Boto3 S3 client within the mocked context, creates a bucket, and then verifies its existence, all without interacting with actual AWS infrastructure. Dummy AWS credentials are set to prevent botocore from attempting real AWS calls."},"warnings":[{"fix":"Replace specific decorators like `@mock_s3` with `@mock_aws`. If you need to specify specific services for the mock, pass them as arguments to `@mock_aws` (though often not necessary for basic usage, it mocks all by default). For example: `@mock_aws(config={'s3': {'use_docker': False}})`.","message":"Moto v5.x introduced a significant breaking change: all individual service decorators (e.g., `@mock_s3`, `@mock_dynamodb`, `@mock_sqs`) have been removed and replaced by a single, unified `@mock_aws` decorator.","severity":"breaking","affected_versions":">= 5.0.0"},{"fix":"Create `boto3` clients/resources inside the `@mock_aws` decorated function, within the `with mock_aws():` block, or within a `setUp` method of a `unittest.TestCase` where the class is decorated. For Pytest, ensure fixtures that create clients are decorated or called within the mock's scope. Using local imports for modules that create `boto3` clients can also help.","message":"Boto3 clients/resources must be created *after* the `moto` mock has been established. If a Boto3 client is initialized globally (e.g., at the module level) before the `@mock_aws` decorator or context manager is activated, `moto` will not intercept those calls, and they may hit real AWS.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Include `region_name='your-desired-region'` in all `boto3.client()` and `boto3.resource()` calls within your mocked tests.","message":"Always specify `region_name` explicitly when creating `boto3` clients and resources (e.g., `boto3.client('s3', region_name='us-east-1')`). Moto can sometimes exhibit inconsistent behavior or default to unexpected regions if `region_name` is omitted, potentially leading to hard-to-debug test failures.","severity":"gotcha","affected_versions":"All versions"},{"fix":"If your tests relied on shared state between methods in a class, refactor them to ensure each test method sets up its required state independently, or use alternative mechanisms (e.g., pytest fixtures with appropriate scope) to manage state if shared setup is truly necessary.","message":"In Moto v3.x, the behavior of class decorators changed: the mock state is now reset before *every* test method within a decorated class. Previously, the state was global and shared across methods in the same class.","severity":"breaking","affected_versions":">= 3.0.0"},{"fix":"Decorate your pytest fixtures with `@mock_aws` if they provision AWS clients, or use the `mock_aws` context manager within the fixture's setup phase. Example: `@pytest.fixture @mock_aws def s3_client(): return boto3.client('s3', region_name='us-east-1')`.","message":"For Pytest users, ensure that any `boto3` client-creating fixtures are correctly integrated with Moto's mocking. If a fixture creates a client before `mock_aws` is active, it won't be mocked.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Before running tests, set environment variables like `AWS_ACCESS_KEY_ID=testing`, `AWS_SECRET_ACCESS_KEY=testing`, `AWS_SECURITY_TOKEN=testing`, `AWS_SESSION_TOKEN=testing`, and `AWS_DEFAULT_REGION=us-east-1`. These can be exported in your test runner or set programmatically.","message":"Moto intercepts HTTP requests and requires dummy AWS credentials to be set (either via environment variables or `~/.aws/credentials`). Without them, `botocore` might attempt to resolve actual credentials or hit real AWS endpoints, leading to errors or unintended side effects.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T17:30:03.374Z","next_check":"2026-06-28T00:00:00.000Z","problems":[{"fix":"Install the moto library using pip. If you need specific AWS service mocks, install them with extras (e.g., `[all]` or `[s3,dynamodb]`).\n```bash\npip install moto[all]\n# Or for specific services:\npip install moto[s3,dynamodb]\n```","cause":"The 'moto' library is not installed in the Python environment where the code is being run.","error":"ModuleNotFoundError: No module named 'moto'"},{"fix":"Replace individual service decorators with the unified `@mock_aws` decorator.\n```python\nfrom moto import mock_aws\n\n@mock_aws\ndef test_my_aws_function():\n    # Your test code here\n    pass\n```","cause":"This error typically occurs when upgrading Moto to version 5.0 or later, as the individual service decorators (like `mock_s3`, `mock_dynamodb2`) have been replaced by a single `@mock_aws` decorator.","error":"ImportError: cannot import name 'mock_s3' from 'moto'"},{"fix":"Ensure that the `moto` decorator (`@mock_aws`) or context manager (`with mock_aws():`) is applied *before* any `boto3` clients or resources are created in your test. Also, it's good practice to set dummy AWS credentials for tests.\n```python\nimport os\nimport boto3\nfrom moto import mock_aws\n\n# Set dummy credentials (optional, but good practice)\nos.environ['AWS_ACCESS_KEY_ID'] = 'testing'\nos.environ['AWS_SECRET_ACCESS_KEY'] = 'testing'\nos.environ['AWS_SECURITY_TOKEN'] = 'testing'\nos.environ['AWS_SESSION_TOKEN'] = 'testing'\nos.environ['AWS_DEFAULT_REGION'] = 'us-east-1'\n\n@mock_aws\ndef test_s3_operation():\n    s3_client = boto3.client('s3', region_name='us-east-1')\n    # Your S3 operations\n    s3_client.create_bucket(Bucket='my-test-bucket')\n```","cause":"This error happens when `boto3` attempts to make an AWS call but cannot find valid credentials, often because the `moto` mock was not correctly activated before the `boto3` client/resource was initialized, or no dummy credentials were provided.","error":"botocore.exceptions.NoCredentialsError: Unable to locate credentials"},{"fix":"Create the necessary AWS resource (e.g., S3 bucket, DynamoDB table) within your `moto` decorated test function or fixture before making calls to it.\n```python\nimport boto3\nfrom moto import mock_aws\n\n@mock_aws\ndef test_list_s3_buckets():\n    s3_client = boto3.client('s3', region_name='us-east-1')\n    s3_client.create_bucket(Bucket='my-test-bucket') # Create the bucket in the mock environment\n    response = s3_client.list_buckets()\n    assert 'my-test-bucket' in [b['Name'] for b in response['Buckets']]\n```","cause":"Within a `moto` mock, AWS resources like S3 buckets or DynamoDB tables do not automatically exist; they must be explicitly created in the mock environment before your code attempts to access them.","error":"botocore.errorfactory.NoSuchBucket: An error occurred (NoSuchBucket) when calling the ListObjects operation: The specified bucket does not exist."}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":"5.2.1","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"s3,dynamodb","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":1.62,"mem_mb":24.9,"disk_size":"116.2M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"all","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":1.69,"mem_mb":24.9,"disk_size":"291.4M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"s3,dynamodb","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.76,"mem_mb":26.4,"disk_size":"115.5M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"all","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.74,"mem_mb":26.4,"disk_size":"285.8M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"s3,dynamodb","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":8.7,"import_time_s":1.18,"mem_mb":24.9,"disk_size":"117M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"all","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":23,"import_time_s":1.19,"mem_mb":24.9,"disk_size":"292M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"s3,dynamodb","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.26,"mem_mb":26.4,"disk_size":"117M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"all","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.24,"mem_mb":26.4,"disk_size":"286M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"s3,dynamodb","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":2.04,"mem_mb":28.1,"disk_size":"125.6M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"all","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":2.1,"mem_mb":28.4,"disk_size":"333.5M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"s3,dynamodb","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.42,"mem_mb":29.9,"disk_size":"125.2M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"all","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.43,"mem_mb":30.3,"disk_size":"328.4M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"s3,dynamodb","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":8.3,"import_time_s":1.79,"mem_mb":28.1,"disk_size":"127M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"all","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":22,"import_time_s":2.09,"mem_mb":28.4,"disk_size":"334M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"s3,dynamodb","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.88,"mem_mb":29.9,"disk_size":"126M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"all","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.92,"mem_mb":30.3,"disk_size":"329M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"s3,dynamodb","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":2.1,"mem_mb":27.8,"disk_size":"115.6M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"all","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":2.2,"mem_mb":28,"disk_size":"324.6M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"s3,dynamodb","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.34,"mem_mb":29.6,"disk_size":"115.1M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"all","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.35,"mem_mb":29.9,"disk_size":"319.4M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"s3,dynamodb","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":7.6,"import_time_s":2.19,"mem_mb":27.8,"disk_size":"117M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"all","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":21,"import_time_s":2.29,"mem_mb":28,"disk_size":"325M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"s3,dynamodb","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.23,"mem_mb":29.6,"disk_size":"116M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"all","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.41,"mem_mb":29.9,"disk_size":"320M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"s3,dynamodb","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":2.04,"mem_mb":28.5,"disk_size":"115.5M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"all","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":2.12,"mem_mb":28.7,"disk_size":"323.9M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"s3,dynamodb","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.28,"mem_mb":30.3,"disk_size":"114.9M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"all","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.35,"mem_mb":30.5,"disk_size":"318.7M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"s3,dynamodb","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":7,"import_time_s":1.93,"mem_mb":28.5,"disk_size":"117M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"all","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":20,"import_time_s":2.17,"mem_mb":28.7,"disk_size":"324M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"s3,dynamodb","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.38,"mem_mb":30.3,"disk_size":"116M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"all","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":2.3,"mem_mb":30.5,"disk_size":"319M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"s3,dynamodb","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":1.55,"mem_mb":26,"disk_size":"116.8M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"all","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":1.62,"mem_mb":26,"disk_size":"285.8M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"s3,dynamodb","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.63,"mem_mb":26.1,"disk_size":"115.7M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"all","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.64,"mem_mb":26.1,"disk_size":"284.7M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"s3,dynamodb","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":10.4,"import_time_s":1.54,"mem_mb":26,"disk_size":"118M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"all","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":27.1,"import_time_s":1.49,"mem_mb":26,"disk_size":"286M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"s3,dynamodb","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.35,"mem_mb":26.1,"disk_size":"117M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"all","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.36,"mem_mb":26.1,"disk_size":"285M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}