如何导入LambdaContext?

时间:2017-06-15 05:36:06

标签: python amazon-web-services aws-lambda

我正在制作AWS Lambda功能。 现在我想isinstance(context,LambdaContext),我希望它适用于AWS Lambda。 但是我在当地进行单元测试。

那么如何导入LambdaContext。

最佳

4 个答案:

答案 0 :(得分:3)

您可以尝试使用LocalStack

  

LocalStack提供了一个易于使用的测试/模拟框架,用于开发云应用程序。

     

目前,重点主要是支持AWS云堆栈。

     

LocalStack在本地计算机上旋转了以下核心Cloud API:

     
    

http://localhost:4567

的API网关          

Kinesis http://localhost:4568

         

DynamoDB http://localhost:4569

         

DynamoDB Streams http://localhost:4570

         

http://localhost:4571

的弹性搜索          

S3 http://localhost:4572

         

Firehose http://localhost:4573

         

Lambda在http://localhost:4574

         

http://localhost:4575

的SNS          

http://localhost:4576

的SQS          

http://localhost:4577

的红移          

ES(Elasticsearch Service)http://localhost:4578

         

http://localhost:4579

的SES          

Route http://localhost:4580

         

http://localhost:4581

上的CloudFormation          

http://localhost:4582

上的CloudWatch   

答案 1 :(得分:3)

刚发现this package,似乎有人用这个问题中其他答案的概念制作了一个点子包。

遇到同样的问题,希望对以后遇到此问题的人有所帮助。

答案 2 :(得分:0)

在/var/runtime/awslambda/bootstrap.py中定义的

LambdaContext类,用于启动用户功能并具有以下结构:

class LambdaContext(object):
    def __init__(self, invokeid, context_objs, client_context, invoked_function_arn=None):
        self.aws_request_id = invokeid
        self.log_group_name = os.environ['AWS_LAMBDA_LOG_GROUP_NAME']
        self.log_stream_name = os.environ['AWS_LAMBDA_LOG_STREAM_NAME']
        self.function_name = os.environ["AWS_LAMBDA_FUNCTION_NAME"]
        self.memory_limit_in_mb = os.environ['AWS_LAMBDA_FUNCTION_MEMORY_SIZE']
        self.function_version = os.environ['AWS_LAMBDA_FUNCTION_VERSION']
        self.invoked_function_arn = invoked_function_arn

        self.client_context = make_obj_from_dict(ClientContext, client_context)
        if self.client_context is not None:
            self.client_context.client = make_obj_from_dict(Client, self.client_context.client)
        self.identity = make_obj_from_dict(CognitoIdentity, context_objs)

    def get_remaining_time_in_millis(self):
        return lambda_runtime.get_remaining_time()

    def log(self, msg):
        str_msg = str(msg)
        lambda_runtime.send_console_message(str_msg, byte_len(str_msg))

如果要在本地环境中模拟它,只需将其添加到脚本中即可:

class ClientContext(object):
    __slots__ = ['custom', 'env', 'client']


def make_obj_from_dict(_class, _dict, fields=None):
    if _dict is None:
        return None
    obj = _class()
    set_obj_from_dict(obj, _dict)
    return obj


def set_obj_from_dict(obj, _dict, fields=None):
    if fields is None:
        fields = obj.__class__.__slots__
    for field in fields:
        setattr(obj, field, _dict.get(field, None))


class LambdaContext(object):
    def __init__(self, invokeid, context_objs, client_context, invoked_function_arn=None):
        self.aws_request_id = invokeid
        self.log_group_name = os.environ['AWS_LAMBDA_LOG_GROUP_NAME']
        self.log_stream_name = os.environ['AWS_LAMBDA_LOG_STREAM_NAME']
        self.function_name = os.environ["AWS_LAMBDA_FUNCTION_NAME"]
        self.memory_limit_in_mb = os.environ['AWS_LAMBDA_FUNCTION_MEMORY_SIZE']
        self.function_version = os.environ['AWS_LAMBDA_FUNCTION_VERSION']
        self.invoked_function_arn = invoked_function_arn

        self.client_context = make_obj_from_dict(ClientContext, client_context)
        if self.client_context is not None:
            self.client_context.client = None
        self.identity = None


    def get_remaining_time_in_millis(self):
        return None

    def log(self, msg):
        str_msg = str(msg)
        print(str_msg)
        # lambda_runtime.send_console_message(str_msg, byte_len(str_msg))

答案 3 :(得分:0)

这不是最严格的意义上的答案,如果不合适,请删除。

我已经尝试了@ Dmitry-Masanov的答案,并为pytest绑定了一个python固定装置,可以在测试脚本本身中使用,也可以在conftest.py文件中使用它。

@pytest.fixture
def mock_lambda_context():
    class ClientContext:
        """
        Class for mocking Context

        Has `custom`, `env`, and `client` `__slots__`
        """

        __slots__ = ["custom", "env", "client"]

    def make_obj_from_dict(_class, _dict, fields=None):
        """
        Makes an object of `_class` from a `dict`

        :param _class: A class representing the context
        :type _class: `ContextClass`
        :param _dict: A dictionary of data 
        :type _dict: `dict`
        :param fields: [description], defaults to None
        :type fields: [type], optional
        :return: An object
        :rtype: `ClientContext` class
        """
        if _dict is None:
            return None
        obj = _class()
        set_obj_from_dict(obj, _dict)
        return obj

    def set_obj_from_dict(obj, _dict, fields=None):
        if fields is None:
            fields = obj.__class__.__slots__
        for field in fields:
            setattr(obj, field, _dict.get(field, None))

    class LambdaContext(object):
        """
        Create a Lambda Context Class object
        """

        def __init__(self, invokeid, client_context, invoked_function_arn=None):
            self.aws_request_id = invokeid
            self.log_group_name = "AWS_LAMBDA_LOG_GROUP_NAME"
            self.log_stream_name = "AWS_LAMBDA_LOG_STREAM_NAME"
            self.function_name = "AWS_LAMBDA_FUNCTION_NAME"
            self.memory_limit_in_mb = "AWS_LAMBDA_FUNCTION_MEMORY_SIZE"
            self.function_version = "AWS_LAMBDA_FUNCTION_VERSION"
            self.invoked_function_arn = invoked_function_arn

            self.client_context = make_obj_from_dict(ClientContext, client_context)
            if self.client_context is not None:
                self.client_context.client = None
            self.identity = None

        def get_remaining_time_in_millis(self):
            return None

        def log(self, msg):
            str_msg = str(msg)
            print(str_msg)

    lambda_context = LambdaContext("AWS_ID", {})

    return lambda_context

我几乎可以肯定我的实现可以改进(OO python不是我的强项),但这可以达到我的目的:

  • 模拟lambda上下文对象
  • 与pytest集成

这可以类似于以下方式使用:

@pytest.mark.smoke
def test_lambda_handler(apigw_event, mock_lambda_context):
    ret = app.lambda_handler(apigw_event, mock_lambda_context)
    assert "log_stream_name" in ret["body"]

再次感谢德米特里,您的回答为我节省了很多麻烦。