简体   繁体   中英

Mocking boto3 calls actual boto3

I'm writing some test for boto3 functions and using the moto library to mock boto3 .

The example they provide is as such:

import boto3
from moto import mock_ec2

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)

@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'

However when I try something similar, using a trivial example here, by doing this:

def start_instance(instance_id):
    client = boto3.client('ec2')
    client.start_instances(InstanceIds=[instance_id])

@mock_ec2
def test_start_instance():
    start_instance('abc123')
    client = boto3.client('ec2')
    instances = client.describe_instances()
    print instances

test_start_instance()

ClientError: An error occurred (InvalidInstanceID.NotFound) when calling the StartInstances operation: The instance ID '[u'abc123']' does not exist

Why is it actually making request to AWS when I clearly have the function wrapped in the mocker?

Looking at the README.md of moto for boto/boto3 , I notice on the S3 connection code, there is a remarks

# We need to create the bucket since this is all in Moto's 'virtual' AWS account

If I am correct, the error shown is not AWS error, but Moto error. You need to initialise all the mock resources you want to mock to the Moto virtual space. This mean, you need to use another script to use moto to mock "create_instance" before you can start the instance.

So after reaching out to some of the contributors I was told that:

Moto isn't like a MagicMock--it's an actual in-memory representation of the AWS resources. So you can't start an instance you haven't created, you can't create an instance in a vpc you haven't previously defined in Moto, etc.

In order to use services that require a certain resource, you first have to create that mock service. For my function to work I went ahead and mocked a call to create_instance which I can then use to test further. Hope this helps those who stumble on this at some point in the future.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM