簡體   English   中英

測試 Python AWS Lambda boto3 初始化

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM