garnaat / placebo

Make boto3 calls that look real but have no effect.
Apache License 2.0
394 stars 28 forks source link

Assistance attaching to client #74

Closed scottstaffiere closed 4 years ago

scottstaffiere commented 5 years ago

I have a Lambda function that I want to test with Placebo. The function (image_search.py) has been simplified, but is similar to this:

import boto3

ec2 = boto3.client("ec2")

def get_images(os_version):
    images = ec2.describe_images(
        Filters=[{"Name": "tag:OS_Version", "Values": [os_version]}], Owners=["self"]
    )
    return images

def lambda_handler(event, context):
    os_version = event["OS_Version"]
    images = get_images(os_version)

From what I've read, it's best to setup the client outside of the handler function to take advantage of Lambda functions that get re-used. I manually recorded responses with Placebo and they're in a folder ready to go.

When I try to unit test with Pytest however, it always fails with "Request has expired" which tells me that it's trying to run live calls. I think it's because when I import the image_search module, it's creating a client before I can attach Placebo to it.

import placebo
from src import image_search

# begin tests here
def test_get_images():
    boto3.setup_default_session()
    session = boto3.DEFAULT_SESSION
    pill = placebo.attach(session, data_path='/path/to/response/directory')
    pill.playback()
    images = rotate_amis.get_images("amazon-linux2")
    tags = images["Images"][0]["Tags"]
    for tag in tags:
        if tag["Key"] == "OS_Version":
            value = tag["Value"]

    assert value == "amazon-linux2"

However if i lazy load the image_search module after I setup Placebo, the tests pass.

import placebo

# begin tests here
def test_get_images():
    boto3.setup_default_session()
    session = boto3.DEFAULT_SESSION
    pill = placebo.attach(session, data_path='/path/to/response/directory')
    pill.playback()
    from src import image_search

    images = rotate_amis.get_images("amazon-linux2")
    tags = images["Images"][0]["Tags"]
    for tag in tags:
        if tag["Key"] == "OS_Version":
            value = tag["Value"]

    assert value == "amazon-linux2"

However this seems really hacky - what is the best way to handle something like this?