Search code examples
pythonamazon-web-servicesboto3moto

How to mock an AWS Lambda with moto


I created a code to invoke a AWS lambda function created somewhere else.

I would like to use moto for testing it, but I don't really understand how to do it and I continue to obtain errors.

This is a simple example of the main code:

import boto3
import json


class SimpleLambda:
    def __init__(self):
        self.aws_lambda = boto3.client("lambda", region_name="eu-west-2")

    def __call__(self):
        try:
            lambda_response = self.aws_lambda.invoke(
                FunctionName="test-lambda",
                Payload=json.dumps(
                    {
                        "Records": [
                            {
                                "Source": "test_source",
                                "Version": "test_version",
                            }
                        ]
                    }
                ),
            )
            return lambda_response["Payload"].read()
        except Exception as err:
            print(f"Could not invoke simple lambda: {err}")
            return None

and the test:

import os
import pytest
import unittest.mock as mock

import boto3
from moto import mock_lambda

from aws_lambda import SimpleLambda


@pytest.fixture
def aws_credentials():
    os.environ["AWS_ACCESS_KEY_ID"] = "testing"
    os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
    os.environ["AWS_SECURITY_TOKEN"] = "testing"
    os.environ["AWS_SESSION_TOKEN"] = "testing"


@pytest.fixture
def lambda_client(aws_credentials):
    with mock_lambda():
        yield boto3.client("lambda", region_name="eu-west-2")


@pytest.fixture
def lambda_test(lambda_client):
    lambda_client.create_function(
        FunctionName="test-lambda",
        Role="arn:aws:iam::123456789012:role/doesnotexist",
        Code={"ZipFile": b"test"}
    )
    yield


def test_simple_lambda_call(lambda_client, lambda_test):
    simple_lambda = SimpleLambda()

    test = simple_lambda()

I obtain the error:

botocore.errorfactory.InvalidParameterValueException: An error occurred (InvalidParameterValueException) when calling the CreateFunction operation: The role defined for the function cannot be assumed by Lambda.

I found several example about how to use moto with S3 bucket, but nothing with lambda.

Running the code in this other question, I obtain the same error.

Any advice?


Solution

  • Moto also validates whether the IAM role exists, just like AWS does.

    So make sure that the IAM role is created first:

    with mock_iam():
        iam = boto3.client("iam", region_name="eu-west-2")
        iam_role = iam.create_role(
            RoleName="my-role",
            AssumeRolePolicyDocument="some policy",
            Path="/my-path/",
        )["Role"]["Arn"]