【问题标题】:aws boto3 unittest function that invokes a Lambda function调用 Lambda 函数的 aws boto3 unittest 函数
【发布时间】:2020-04-09 16:33:43
【问题描述】:

我有一个调用 AWS Lambda 函数的 python 函数。

#lambda.py
import boto3
import os

client    = boto3.client('lambda')
MY_LAMBDA = os.environ['MY_LAMBDA']

def invoke_function(input):
    response = client.invoke(
        FunctionName=MY_LAMBDA,
        InvocationType='RequestResponse',
        Payload=json.dumps(input)
    )

如何为此函数创建单元测试?我一直在将 Moto 用于其他 AWS 服务,但无法使其适用于 Lambda。

我尝试使用 moto:

#test_lambda.py

from unittest.mock import MagicMock, patch
from unittest.mock import ANY
from moto import mock_lambda
import boto3
import os
import zipfile
import io
import lambda

class LambdaTest(unittest.TestCase):

    def get_test_zip_file(self):
        pfunc = '''
                def lambda_handler(event, context):
                    return event
                '''
        zip_output = io.BytesIO()
        zip_file = zipfile.ZipFile(zip_output, 'w', zipfile.ZIP_DEFLATED)
        zip_file.writestr('lambda_function.py', pfunc)
        zip_file.close()
        zip_output.seek(0)
        return zip_output.read()

    @mock_lambda
    def test_invoke_requestresponse_function(self):
        conn = boto3.client('lambda', 'us-east-1')
        conn.create_function(
            FunctionName='test-func',
            Runtime='python3.8',
            Role='test-iam-role',
            Handler='lambda_function.lambda_handler',
            Code={
                'ZipFile': self.get_test_zip_file(),
            },
            Description='test lambda function',
            Timeout=3,
            MemorySize=128,
            Publish=True
        )

        sample_input = {'msg': 'Test Input'}

        result = lambda.invoke_function(sample_input)

这个错误是:

botocore.exceptions.ClientError: An error occurred (404) when calling the Invoke operation: 

【问题讨论】:

  • 客户端的初始化好像少了一些代码,请问可以在sn-p中添加吗?
  • @Maurice 用客户端初始化更新了 sn-p。
  • 你在哪里设置os.environ['MY_LAMBDA']
  • 我在运行测试之前导出了那个环境变量。 export MY_LAMBDA=test-func
  • 这方面有什么更新吗?

标签: amazon-web-services aws-lambda boto3 python-unittest moto


【解决方案1】:

lambda.py 中的 boto3-client 在任何模拟发生之前被初始化。由于该客户端不知道它正在被嘲笑,它可能会尝试与 AWS 本身对话。

对于您特定的测试用例,有几个解决方案:

  • import lambda 放在测试本身中,这样 boto3-client 在装饰器初始化后创建
  • 用模拟版本覆盖客户端:lambda.client = conn
  • 将模拟的客户端作为参数传递给 lambda.invoke_function(conn, sample_input)

【讨论】: