如何在 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(写作方式)时遇到了困难,所以无法表达我的问题。所以,我有以下问题:
- 在我的 python 文件中,我没有 class.I 在方法之外像这样实例化 s3:s3 = boto3.resource('s3')。那么,我如何模拟这个 s3 对象并传递给方法,以便使用该模拟对象。
- 在我的测试 class 中,我将主要的 python 导入为:import jsontoxmlconverter as converter
然后使用 converter.<> 进行单元测试,但该方法不将 s3 作为参数,所以再次说明,我如何传递 s3 模拟对象。
- 我读过一些关于使用 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
对象是替代 s3
的 mock.Mock
对象;您可以在调用依赖于它们的函数之前自由地重新分配它的属性。
我有一个简单的 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(写作方式)时遇到了困难,所以无法表达我的问题。所以,我有以下问题:
- 在我的 python 文件中,我没有 class.I 在方法之外像这样实例化 s3:s3 = boto3.resource('s3')。那么,我如何模拟这个 s3 对象并传递给方法,以便使用该模拟对象。
- 在我的测试 class 中,我将主要的 python 导入为:import jsontoxmlconverter as converter 然后使用 converter.<> 进行单元测试,但该方法不将 s3 作为参数,所以再次说明,我如何传递 s3 模拟对象。
- 我读过一些关于使用 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
对象是替代 s3
的 mock.Mock
对象;您可以在调用依赖于它们的函数之前自由地重新分配它的属性。