测试Python AWS Lambda boto3初始化

测试Python AWS Lambda boto3初始化,python,amazon-web-services,mocking,boto3,python-unittest,Python,Amazon Web Services,Mocking,Boto3,Python Unittest,对于lambda,需要在处理程序外部初始化依赖项 我正在创建一个简单的python函数,其工作原理与蓝图类似: import boto3 s3 = boto3.client('ssm') def lambda_handler(event, context): # some code here 测试呢 from lambda_function import handler # Option 1 import lambda_function # Optio

对于lambda,需要在处理程序外部初始化依赖项

我正在创建一个简单的python函数,其工作原理与蓝图类似:

import boto3


s3 = boto3.client('ssm')


def lambda_handler(event, context):
    # some code here
测试呢

from lambda_function import handler # Option 1
import lambda_function              # Option 2

class TestHandler(unittest.TestCase):

    @patch('lambda_function.handler.boto3.client')
    def test(self, boto3_mock):
        # ...
我似乎无法正确设置模拟,以便
boto.client
调用不会出错,因为
必须指定一个区域。

选项1
上,它在导入调用期间出错,在
选项2
上,它在
补丁
设置期间出错

我不能使用
~/.aws/config
,因为它将用于不具备该功能的CI。我也不想更改boto.client调用以包含默认区域


有什么我遗漏的吗?

虽然我不确定上面的代码有什么问题,但我建议您在尝试用Python()模拟AWS服务时使用moto库:

此外,作为个人偏好,我建议不要在实际的lambda函数中加入太多逻辑。只需将传入事件尽可能多地发送给其他函数/类即可。这将有助于简化测试

如果你真的想继续使用@patch而不是moto库,我得到了以下代码:

from mock import patch
from example import lambda_function

class TestStringMethods(unittest.TestCase):

    @patch('example.lambda_function.boto3.client')
    def test_my_model(self, some_mock):
        # further setup of test
        lambda_function.my_handler(None, None)

这里,lambda_函数是包含处理程序的文件,它位于目录/包示例中。您还可以使用“example.lambda_function.boto3”模拟boto3本身,并自己返回一个客户端。

我的客户端类中的boto3 s3客户端和pytest中的moto都有相同的问题。我通过将boto3客户端包装成一个单例解决了这个问题:

这是我的客户端代码hello_world/app.py

class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
    if cls not in cls._instances:
        cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
    return cls._instances[cls]

class S3BotoClient(metaclass=Singleton):
    def __init__(self, *args):
        print(f"creating s3 cient with args {args}")
        self.client = boto3.client("s3", *args)

def lambda_handler(event, context):
    s3 = S3BotoClient().client
    s3.list_buckets()
这是一个单元测试:

from moto import mock_s3
from hello_world import app

@pytest.fixture()
def apigw_event():
    # return some sample event here

@mock_s3
def test_lambda_handler(apigw_event):
    ret = app.lambda_handler(apigw_event, "")
    ret = app.lambda_handler(apigw_event, "")
    # do assertions here

因此,S3客户端只实例化一次,并且在moto virtual env初始化之后

谢谢@hieron,逻辑不在实际的lambda处理程序上,因此测试代码很好,我的问题是测试设置。上述示例的问题是源代码中的
boto.client
调用将在示例的第3行执行(
来自lambda_函数导入处理程序
),并给出区域错误。您可以尝试我在回答中添加的建议吗?
from moto import mock_s3
from hello_world import app

@pytest.fixture()
def apigw_event():
    # return some sample event here

@mock_s3
def test_lambda_handler(apigw_event):
    ret = app.lambda_handler(apigw_event, "")
    ret = app.lambda_handler(apigw_event, "")
    # do assertions here