python - 如何模拟 boto3 的 StreamingBody 对象以在 Python 中使用 BytesIO 进行处理?
问题描述
我正在对一个将元素从 S3 对象转换为 pandas DataFrame 的函数进行单元测试,并且需要模拟从 boto3 返回的 StreamingBody 对象
文件.py
def object_to_df(self, key_name, dtypes):
s3_object = self.get_object(key_name=key_name)
if s3_object is not None:
object_df = pandas.read_csv(
io.BytesIO(s3_object["Body"].read()), dtype=dtypes
)
return object_df
self.get_object(key_name) 的响应记录在这里
{
'Body': StreamingBody(),
'DeleteMarker': True|False,
'AcceptRanges': 'string',
...
}
所以我需要模拟那个 StreamingBody() 对象并让我的模拟函数返回它。
测试.py
import unittest
import pandas
from io import StringIO
from unittest.mock import patch, Mock
from path.to.file import custom_class
from botocore.response import StreamingBody
class TestS3Class(unittest.TestCase):
"""TestCase for path_to/file.py"""
def setUp(self):
"""Creates an instance of the live class for testing"""
self.s3_test_client = S3()
@patch('path.to.class.get_object')
def test_object_to_df(self, mock_get_object):
""""""
mock_response = {'Body': [{'Candidate': 'Black Panther', 'Votes': 3},
{'Candidate': 'Captain America: Civil War', 'Votes': 8},
{'Candidate': 'Guardians of the Galaxy', 'Votes': 8},
{'Candidate': "Thor: Ragnarok", 'Votes': 1}
]}
mock_stream = StreamingBody(StringIO(str(mock_response)), len(str(mock_response)))
mock_get_object.return_value = mock_stream
self.assertIsInstance(self.s3_test_client.object_to_df(key_name='key_name', dtypes=str), pandas.DataFrame)
但我遇到了TypeError: 'StreamingBody' object is not subscriptable
有什么提示吗?
解决方案
S3 客户端返回一个字典,而您的模拟 S3 客户端返回一个 StreamingBody。您模拟的 S3 客户端应该返回类似
body_json = {
'Body': [
{'Candidate': 'Black Panther', 'Votes': 3},
{'Candidate': 'Captain America: Civil War', 'Votes': 8},
{'Candidate': 'Guardians of the Galaxy', 'Votes': 8},
{'Candidate': "Thor: Ragnarok", 'Votes': 1}
]
}
body_encoded = json.dump(body_json).encode("utf-8")
body = StreamingBody(
StringIO(body_encoded),
len(body_encoded)
)
mocked_response = {
'Body': body,
...
}
mock_get_object.return_value = mocked_response
推荐阅读
- javascript - Array.includes 的功能使用导致 TypeError
- php - Laravel hasMany to Belongs 返回 undefined
- python - TensorFlow conv1d_transpose 过滤器值
- javascript - 执行包返回:Haste 模块映射中不存在模块 util
- apache-kafka - kafka-streams 加入产生重复项
- azure - 如何在 AzureFunction 日志中查看异常信息
- sql - 如何区分转换中的插入和更新
- ios - 没有这样的模块“FirebaseFirestore”
- javascript - Redux Form 不会改变值
- android - android.support.multidex.MultiDexApplication 无法转换为应用名称