[英]Testing Python AWS Lambda boto3 initialization
对于 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
调用不会因You must specify a region.
而出错You must specify a region.
在Option 1
它在导入调用期间出错,而在Option 2
它在patch
设置期间出错
我不能使用~/.aws/config
因为它将用于不能拥有它的 CI 上。 我也不想更改boto.client
调用以包含默认区域。
有什么我想念的吗?
虽然我不确定上述代码的问题是什么,但我建议您在尝试在 Python 中模拟 AWS 服务时使用 moto 库( https://github.com/splec/moto ):
import boto3
from moto import mock_s3
from lambda_function import handler
class TestHandler(unittest.TestCase):
@mock_s3
def test(self, boto3_mock):
# setup your connection to s3 or ssm. Make sure this matches the setup in the lambda file.
conn = boto3.client('s3')
conn.create_bucket(Bucket='mybucket') # setup your fake resources
# call your lambda function
此外 - 作为个人偏好 - 我建议不要在您的实际 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_function是包含您的处理程序的文件,它位于目录/包example 中。 您还可以使用'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 初始化之后
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.