如何在 AWS 中为 AWS lambda 函数模拟 s3.Object

how to mock s3.Object for an AWS lambda function in AWS

我有一个简单的 lambda 函数,因为我是 Python 的新手,所以我无法为该函数编写测试用例。因此,任务非常简单,我将 xml 文档上传到 s3,并返回 url。下面是主 python 文件中的代码:

编辑 2:以下代码的目的是从 JSON 有效负载中生成 xml,作为参数根传入,并将其上传到 s3。 s3 已经有一个 bucket s3-encora-task,我要上传 output.xml。我必须为那个条件编写单元测试。

def uploaddata(root):
    xmlstr = minidom.parseString(ET.tostring(root)).toprettyxml(indent="   ")
    string_out = io.StringIO()
    string_out.write(xmlstr)
    s3.Object('s3-encora-task', 'output.xml').put(Body=string_out.getvalue())
    location = boto3.client('s3').get_bucket_location(Bucket=bucket_name)['LocationConstraint']
    url = "https://s3-%s.amazonaws.com/%s/%s" % (location, bucket_name, 'output.xml')
    return url

我在行中收到错误:

s3.Object('s3-encora-task', 'output.xml').put(Body=string_out.getvalue())

错误如下:

引发 NoCredentialsError() botocore.exceptions.NoCredentialsError: 无法找到凭据

我有写Junit测试的经验classes,但是我在比较Junit和unittest(写作方式)时遇到了困难,所以无法表达我的问题。所以,我有以下问题:

  1. 在我的 python 文件中,我没有 class.I 在方法之外像这样实例化 s3:s3 = boto3.resource('s3')。那么,我如何模拟这个 s3 对象并传递给方法,以便使用该模拟对象。
  2. 在我的测试 class 中,我将主要的 python 导入为:import jsontoxmlconverter as converter 然后使用 converter.<> 进行单元测试,但该方法不将 s3 作为参数,所以再次说明,我如何传递 s3 模拟对象。
  3. 我读过一些关于使用 moto 模拟 s3 的内容,但无法弄清楚对象是如何传递的,因此任何更多信息都会有所帮助。

提前致谢!!

编辑 1: 下面是我测试中的当前代码 class:

     import jsontoxmlconverter as converter
    def test_jsontoxml_happyflow(self):
        with open('jsonData.txt') as json_file:
            data = json.load(json_file)
        mock = Mock()
        mock.patch('converter.s3')
        result = converter.jsontoxml(data, context={})

使用mock.patch:

import jsontoxmlconverter as converter
from mock import patch

def test_jsontoxml_happyflow(self):
    with patch('jsontoxmlconverter.s3') as mock_s3:
        # make whatever adjustments to mock_s3 as needed
        result = converter.uploaddata("foo")

请注意,您需要告诉 patch 您要在哪个模块中修补 s3。当您使用 patch 作为上下文管理器时,修补程序仅适用于上下文,这很容易隔离这样的更改并保证它们不会影响其他测试。上下文中可用的 mock_s3 对象是替代 s3mock.Mock 对象;您可以在调用依赖于它们的函数之前自由地重新分配它的属性。