【问题标题】:Mocking a lambda response with moto用 moto 模拟 lambda 响应
【发布时间】:2020-12-29 00:49:57
【问题描述】:

在我的代码中的某处,调用 lambda 以返回真/假响应。我试图在我的单元测试中模拟这个 lambda,但没有成功。

这是我的代码:

def _test_update_allowed():
    old = ...
    new = ...
    assert(is_update_allowed(old, new) == True)

在内部,is_update_allowed 调用 lambda,这是我想要模拟的。

我尝试在测试上方添加以下代码:

import zipfile
import io
import boto3
import os

@pytest.fixture(scope='function')
def aws_credentials():
    """Mocked AWS Credentials for moto."""
    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'


CLIENT = boto3.client('lambda', region_name='us-east-1')

# Expected response setup and zip file for lambda mock creation
def lambda_event():
    code = '''
        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', code)
    zip_file.close()
    zip_output.seek(0)
    return zip_output.read()

# create mocked lambda with zip file
def mock_some_lambda(lambda_name, return_event):
    return CLIENT.create_function(
        FunctionName=lambda_name,
        Runtime='python2.7',
        Role='arn:aws:iam::123456789:role/does-not-exist',
        Handler='lambda_function.lambda_handler',
        Code={
            'ZipFile': return_event,
        },
        Publish=True,
        Timeout=30,
        MemorySize=128
    )

然后将我的测试更新为:

@mock_lambda
def _test_update_allowed():
    mock_some_lambda('hello-world-lambda', lambda_event())
    old = ...
    new = ...
    assert(is_update_allowed(old, new) == True)

但我收到以下错误,这让我认为它实际上是在尝试与 AWS 对话

botocore.exceptions.ClientError: An error occurred (UnrecognizedClientException) when calling the CreateFunction operation: The security token included in the request is invalid.

【问题讨论】:

  • 我会在那里放一个断点......然后通过上下调用堆栈来查看发生了什么
  • 由于某种原因,lambda 的角色需要存在并与 lambda.amazonaws.com 建立信任关系

标签: python unit-testing aws-lambda boto moto


【解决方案1】:

从错误消息中,我可以确认这绝对不是 AWS 问题。它清楚地表明它正在尝试使用一些无效的凭据。所以这归结为代码。

我假设您已经有必要库的导入语句,因为这些在共享代码中也不可见

import pytest
import moto

from mock import mock, patch
from moto import mock_lambda

所以你需要使用

def aws_credentials():
 .....

在创建客户端时,因为从代码中我看不到您使用的是相同的。

@pytest.fixture(scope='function')
def lambda_mock(aws_credentials):
with mock_lambda():
    yield boto3.client('lambda', region_name='us-east-1')

最终你的模拟

@pytest.fixture(scope='function')
def mock_some_lambda(lambda_mock):
    lambda_mock.create_function(
        FunctionName=lambda_name,
        Runtime='python2.7',
        Role='arn:aws:iam::123456789:role/does-not-exist',
        Handler='lambda_function.lambda_handler',
        Code={
            'ZipFile': return_event,
        },
        Publish=True,
        Timeout=30,
        MemorySize=128
    )
 yield

然后测试函数

    def _test_update_allowed(lambda_mock,mock_some_lambda):
        lambda_mock.invoke(...)
          .....

不能给出一个可行的例子,因为不确定完整的逻辑是什么。看看this之间的帖子。

【讨论】:

  • 我得到 botocore.exceptions.ClientError: An error occurred (404) when calling the Invoke operation when I do it but it works all fine when I put mock_some_lambda and test function together.我错过了什么?
  • @Naxi,404 表示未找到。听起来 moto 找不到您正在测试的代码试图调用的 lambda 函数。我会检查您创建的函数的名称和您调用的函数的名称是否匹配。
猜你喜欢
  • 1970-01-01
  • 2022-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-14
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
相关资源
最近更新 更多