英文:
Assertion error for BytesIO object in Python unittest
问题
以下是要翻译的内容:
I have a core logic classes like below:
class SomeDBTManifestProvider:
def __init__(self):
pass
def extract_manifest_json(self, file_stream: BytesIO):
try:
zipf = zipfile.ZipFile(file_stream)
manifest_json_text = [zipf.read(name) for name in zipf.namelist() if "/manifest.json" in name][0].decode("utf-8")
return json.loads(manifest_json_text)
except Exception as e:
raise FetchManifestJsonException(e)
class DbtProvisioner(object):
def __init__(self, dbt_manifest_provider: SomeDBTManifestProvider):
self.dbt_manifest_provider = dbt_manifest_provider
def provision(self, provision_request: ProvisionRequest):
self.dbt_manifest_provider.extract_manifest_json(BytesIO(b'ABC'))
return "Success"
Where ProvisionRequest
is nothing but a DataClass
and it can be ignored for now. As it can be seen DbtProvisioner
is dependent on SomeDBTManifestProvider
, therefore I have used D.I to access the method of SomeDBTManifestProvider
. Now, I want to test DbtProvisioner
for which I wrote the below test case:
def test_dbt_provision(self):
provision_request = ProvisionRequest(
DataProduct("a", "b", "c", "d", "e", "f", {}, [{}]), Workload("ab", "cd", "ef", "gh", DbtAttr("path"))
)
dbt_manifest = Mock()
actual = DbtProvisioner(dbt_manifest).provision(
provision_request)
dbt_manifest.extract_manifest_json.assert_called_with(BytesIO(b'ABC'))
self.assertEqual("Success", actual)
Now, using the above approach I want to ensure that my method has been called with the right set of arguments. But somehow, it is giving me the below error:
Expected: extract_manifest_json(<_io.BytesIO object at 0x10d675900>)
Actual: extract_manifest_json(<_io.BytesIO object at 0x10f8efef0>)
How do I resolve this error? What am I missing here?
I also referred to multiple articles from SO but didn't help in any way. TIA
英文:
I have a core logic classes like below:
class SomeDBTManifestProvider:
def __init__(self):
pass
def extract_manifest_json(self, file_stream: BytesIO):
try:
zipf = zipfile.ZipFile(file_stream)
manifest_json_text = [zipf.read(name) for name in zipf.namelist() if "/manifest.json" in name][0].decode("utf-8")
return json.loads(manifest_json_text)
except Exception as e:
raise FetchManifestJsonException(e)
class DbtProvisioner(object):
def __init__(self, dbt_manifest_provider: SomeDBTManifestProvider):
self.dbt_manifest_provider = dbt_manifest_provider
def provision(self, provision_request: ProvisionRequest):
self.dbt_manifest_provider.extract_manifest_json(BytesIO(b'ABC'))
return "Success"
Where ProvisionRequest
is nothing but a DataClass
and it can be ignored for now. As it can be seen DbtProvisioner
is dependent on SomeDBTManifestProvider
, therefore I have used D.I to access the method of SomeDBTManifestProvider
. Now, I want to test DbtProvisioner
for which I wrote the below test case:
def test_dbt_provision(self):
provision_request = ProvisionRequest(
DataProduct("a", "b", "c", "d", "e", "f", {}, [{}]), Workload("ab", "cd", "ef", "gh", DbtAttr("path"))
)
dbt_manifest = Mock()
actual = DbtProvisioner(dbt_manifest).provision(
provision_request)
dbt_manifest.extract_manifest_json.assert_called_with(BytesIO(b'ABC'))
self.assertEqual("Success", actual)
Now, using the above approach I want to ensure that my method has been called with the right set of arguments. But somehow, it is giving me the below error:
Expected: extract_manifest_json(<_io.BytesIO object at 0x10d675900>)
Actual: extract_manifest_json(<_io.BytesIO object at 0x10f8efef0>)
How do I resolve this error? What am I missing here?
I also referred to multiple articles from SO but didn't help in any way. TIA
答案1
得分: 1
问题在于BytesIO
对象的比较是基于身份(identity)而不是内容(content),所以虽然b'ABC' == b'ABC'
是正确的,但BytesIO(b'ABC') == BytesIO(b'ABC')
是错误的,因为它们是两个不同的BytesIO
对象。
为了按预期执行您的测试,一个解决方法是使用getvalue
方法提取作为调用参数使用的BytesIO
对象的值,该值可以在Mock
对象的mock_calls
属性中找到。
将:
dbt_manifest.extract_manifest_json.assert_called_with(BytesIO(b'ABC'))
改为:
self.assertEqual(dbt_manifest.extract_manifest_json.mock_calls[0].args[0].getvalue(), b'ABC')
英文:
The problem is that BytesIO
objects do not compare to each other based on content, but identity, so while b'ABC' == b'ABC'
is true, BytesIO(b'ABC') == BytesIO(b'ABC')
is not because they are two different BytesIO
objects.
To perform your test as desired, a workaround would be to use the getvalue
method to extract the value of the BytesIO
object used as the argument of the call, which can be found in the mock_calls
attribute of the Mock
object.
Change:
dbt_manifest.extract_manifest_json.assert_called_with(BytesIO(b'ABC'))
to:
self.assertEqual(dbt_manifest.extract_manifest_json.mock_calls[0].args[0].getvalue(), b'ABC'))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论