PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Friday, November 4, 2022

[FIXED] How to emulate locally aws context for testing

 November 04, 2022     amazon-web-services, lambda, pytest, python     No comments   

Issue

I have created a lambda where I retrieve region, based on the context.invoked_function_arn.

So, I would like to create and emulate this behavior using a test script file not via conftest.py because I have other unit test methods implemented in the same test script.

I find this link lambda-context which is useful and implemented the same concept in my test script. However all the time, I'm getting the AttributeError: 'function' object has no attribute 'invoked_function_arn' error message.

@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 = "arn:aws:lambda:eu-west-1:123456789012:function:" \
                                        "ExampleLambdaFunctionResourceName-AULC3LB8Q02F"

            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)

    context = LambdaContext("AWS_ID", {})

    return context

def test_handler(events, mock_lambda_context):
    res = handler(events, mock_lambda_context)
    assert res['context.invoked_function_arn'] == "arn:aws:lambda:eu-west-1:123456789012:function:ExampleLambdaFunctionResourceName-AULC3LB8Q02F" 

Can anyone point me how to fix this silly one?


Solution

I created a sample_context.json like this:

{
    "invoked_function_arn": "arn:aws:lambda:eu-west-1:123456789012:function:ExampleLambdaFunctionResourceName-AULC3LB8Q02F",
    "log_group_name": "/aws/lambda/ExampleLambdaFunctionResourceName-AULC3LB8Q02F",
    "function_name": "ExampleLambdaFunctionResourceName-AULC3LB8Q02F",
    "function_version": "$LATEST"
}

Then in my main test file:

    @pytest.fixture
    def context_outcome():
        return load_json_from_file('sample_context.json')
    
    
    @pytest.fixture
    def context(context_outcome):
        response = type('new', (object,), context_outcome)
        seqs = tuple, list, set, frozenset
        for i, j in context_outcome.items():
            if isinstance(j, dict):
                setattr(response, i, context(j))
            elif isinstance(j, seqs):
                setattr(response, i,
                        type(j)(context(sj) if isinstance(sj, dict) else sj for sj in j))
            else:
                setattr(response, i, j)
        return response

def test_main(events, context):
    assert context.invoked_function_arn == "arn:aws:lambda:eu-west-1:123456789012:function:ExampleLambdaFunctionResourceName-AULC3LB8Q02F"


Answered By - change198
Answer Checked By - Candace Johnson (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing