Github: https://github.com/spulec/moto
Moto-Mock AWSサービス
一言で言えば
Motoは、テストでAWSサービスを簡単に模倣できるようにするライブラリです。
あなたがテストしたい次のPythonコードを持っていると想像してください:
import boto3
class MyModel(object):
def __init__(self, name, value):
self.name = name
self.value = value
def save(self):
s3 = boto3.client('s3', region_name='us-east-1')
s3.put_object(Bucket='mybucket', Key=self.name, Body=self.value)
あなたが過去にそれをどのようにテストしたかを考えてみてください。
今、あなたがMotoでそれをテストする方法を見てみましょう:
import boto3
from moto import mock_s3
from mymodule import MyModel
@mock_s3
def test_my_model_save():
conn = boto3.resource('s3', region_name='us-east-1')
# We need to create the bucket since this is all in Moto's 'virtual' AWS account
conn.create_bucket(Bucket='mybucket')
model_instance = MyModel('steve', 'is awesome')
model_instance.save()
body = conn.Object('mybucket', 'steve').get()['Body'].read().decode("utf-8")
assert body == b'is awesome'
デコレータがテストをラップすると、s3へのすべての呼び出しが自動的に嘲笑されます。 モックはバケツとキーの状態を保持します。
それはさらに良くなる! MotoはPythonコードだけではなく、S3だけではありません。 他の言語でMotoを実行する方法の詳細については、 スタンドアロンサーバーモードを参照してください。 実装されている他のAWSサービスのステータスは次のとおりです。
|------------------------------------------------------------------------------|
| Service Name | Decorator | Development Status |
|------------------------------------------------------------------------------|
| ACM | @mock_acm | all endpoints done |
|------------------------------------------------------------------------------|
| API Gateway | @mock_apigateway | core endpoints done |
|------------------------------------------------------------------------------|
| Autoscaling | @mock_autoscaling| core endpoints done |
|------------------------------------------------------------------------------|
| Cloudformation | @mock_cloudformation| core endpoints done |
|------------------------------------------------------------------------------|
| Cloudwatch | @mock_cloudwatch | basic endpoints done |
|------------------------------------------------------------------------------|
| CloudwatchEvents | @mock_events | all endpoints done |
|------------------------------------------------------------------------------|
| Data Pipeline | @mock_datapipeline| basic endpoints done |
|------------------------------------------------------------------------------|
| DynamoDB | @mock_dynamodb | core endpoints done |
| DynamoDB2 | @mock_dynamodb2 | all endpoints + partial indexes |
|------------------------------------------------------------------------------|
| EC2 | @mock_ec2 | core endpoints done |
| - AMI | | core endpoints done |
| - EBS | | core endpoints done |
| - Instances | | all endpoints done |
| - Security Groups | | core endpoints done |
| - Tags | | all endpoints done |
|------------------------------------------------------------------------------|
| ECR | @mock_ecr | basic endpoints done |
|------------------------------------------------------------------------------|
| ECS | @mock_ecs | basic endpoints done |
|------------------------------------------------------------------------------|
| ELB | @mock_elb | core endpoints done |
|------------------------------------------------------------------------------|
| ELBv2 | @mock_elbv2 | all endpoints done |
|------------------------------------------------------------------------------|
| EMR | @mock_emr | core endpoints done |
|------------------------------------------------------------------------------|
| Glacier | @mock_glacier | core endpoints done |
|------------------------------------------------------------------------------|
| IAM | @mock_iam | core endpoints done |
|------------------------------------------------------------------------------|
| IoT | @mock_iot | core endpoints done |
| | @mock_iotdata | core endpoints done |
|------------------------------------------------------------------------------|
| Lambda | @mock_lambda | basic endpoints done, requires |
| | | docker |
|------------------------------------------------------------------------------|
| Logs | @mock_logs | basic endpoints done |
|------------------------------------------------------------------------------|
| Kinesis | @mock_kinesis | core endpoints done |
|------------------------------------------------------------------------------|
| KMS | @mock_kms | basic endpoints done |
|------------------------------------------------------------------------------|
| Polly | @mock_polly | all endpoints done |
|------------------------------------------------------------------------------|
| RDS | @mock_rds | core endpoints done |
|------------------------------------------------------------------------------|
| RDS2 | @mock_rds2 | core endpoints done |
|------------------------------------------------------------------------------|
| Redshift | @mock_redshift | core endpoints done |
|------------------------------------------------------------------------------|
| Route53 | @mock_route53 | core endpoints done |
|------------------------------------------------------------------------------|
| S3 | @mock_s3 | core endpoints done |
|------------------------------------------------------------------------------|
| SES | @mock_ses | all endpoints done |
|------------------------------------------------------------------------------|
| SNS | @mock_sns | all endpoints done |
|------------------------------------------------------------------------------|
| SQS | @mock_sqs | core endpoints done |
|------------------------------------------------------------------------------|
| SSM | @mock_ssm | core endpoints done |
|------------------------------------------------------------------------------|
| STS | @mock_sts | core endpoints done |
|------------------------------------------------------------------------------|
| SWF | @mock_swf | basic endpoints done |
|------------------------------------------------------------------------------|
| X-Ray | @mock_xray | all endpoints done |
|------------------------------------------------------------------------------|
もう一つの例
新しいec2インスタンスを起動するための関数があるとします。
import boto3
def add_servers(ami_id, count):
client = boto3.client('ec2', region_name='us-west-1')
client.run_instances(ImageId=ami_id, MinCount=count, MaxCount=count)
それをテストするには:
from . import add_servers
from moto import mock_ec2
@mock_ec2
def test_add_servers():
add_servers('ami-1234abcd', 2)
client = boto3.client('ec2', region_name='us-west-1')
instances = client.describe_instances()['Reservations'][0]['Instances']
assert len(instances) == 2
instance1 = instances[0]
assert instance1['ImageId'] == 'ami-1234abcd'
boto2でmoto 1.0.Xを使う
moto 1.0.Xモックドクターはboto3用に定義されており、boto2では動作しません。 @mock_AWSSVC_deprecatedを使用してboto2を操作してください。
boto2でモトを使う
from moto import mock_ec2_deprecated
import boto
@mock_ec2_deprecated
def test_something_with_ec2():
ec2_conn = boto.ec2.connect_to_region('us-east-1')
ec2_conn.get_only_instances(instance_ids='i-123456')
boto2とboto3の両方を使用する場合、混乱を避けるためにこれを行うことができます:
from moto import mock_ec2_deprecated as mock_ec2_b2
from moto import mock_ec2
使用法
すべてのサービスは、デコレータ、コンテキストマネージャ、または生の形式で使用できます。
デコレータ
@mock_s3
def test_my_model_save():
# Create Bucket so that test can run
conn = boto3.resource('s3', region_name='us-east-1')
conn.create_bucket(Bucket='mybucket')
model_instance = MyModel('steve', 'is awesome')
model_instance.save()
body = conn.Object('mybucket', 'steve').get()['Body'].read().decode()
assert body == 'is awesome'
コンテキストマネージャ
def test_my_model_save():
with mock_s3():
conn = boto3.resource('s3', region_name='us-east-1')
conn.create_bucket(Bucket='mybucket')
model_instance = MyModel('steve', 'is awesome')
model_instance.save()
body = conn.Object('mybucket', 'steve').get()['Body'].read().decode()
assert body == 'is awesome'
生の使用
def test_my_model_save():
mock = mock_s3()
mock.start()
conn = boto3.resource('s3', region_name='us-east-1')
conn.create_bucket(Bucket='mybucket')
model_instance = MyModel('steve', 'is awesome')
model_instance.save()
assert conn.Object('mybucket', 'steve').get()['Body'].read().decode() == 'is awesome'
mock.stop()
スタンドアロンサーバーモード
Motoにはスタンドアロンのサーバーモードもあります。 これにより、Pythonを使用しなくてもMotoのバックエンド構造を利用することができます。
デフォルトの依存関係ではないフラスコを使用します。 あなたは次のものを使ってサーバーの「特別な」パッケージをインストールすることができます:
pip install moto[server]
その後、サービスを実行して起動することができます。
$ moto_server ec2
* Running on http://127.0.0.1:5000/
ポートを渡すこともできます:
$ moto_server ec2 -p3000
* Running on http://127.0.0.1:3000/
サーバーを外部から使用できるようにするには、IPアドレスを渡してホスト名としてバインドするか、0.0.0.0の外部インターフェイスを許可します。
$ moto_server ec2 -H 0.0.0.0
* Running on http://0.0.0.0:5000/
これにより、他のネットワークユーザーがサーバーにアクセスできる可能性があります。
次に、 localhostに移動して実行中のインスタンスのリストを表示します(まだ追加していないので空になります)。
上記のより簡単なデコレータを使用することを強くお勧めします)、最も簡単な方法は、次の値を持つboto設定ファイル( ~/.boto
)を作成することです。
[Boto]
is_secure = False
https_validate_certificates = False
proxy_port = 5000
proxy = 127.0.0.1
これでboto3を使いたい場合は、 endpoint_url
をリソースに渡すことができendpoint_url
boto3.resource(
service_name='s3',
region_name='us-west-1',
endpoint_url='http://localhost:5000',
)
インストール
$ pip install moto