gpt4 book ai didi

python - 使用 mock.patch 和 mock_open 模拟包含 JSON 数据的文件

转载 作者:太空宇宙 更新时间:2023-11-04 02:04:38 25 4
gpt4 key购买 nike

我正在尝试测试一种需要在 Python 3.6 中使用 json.load 的方法。经过几次尝试,我尝试“正常”运行测试(使用 CLI 中的常用 unittest.main()),并在 iPython REPL 中运行。

具有以下功能(为示例目的而简化)

def load_metadata(name):
with open("{}.json".format(name)) as fh:
return json.load(fh)

通过以下测试:

class test_loading_metadata(unittest2.TestCase):
@patch('builtins.open', new_callable=mock_open(read_data='{"disabled":True}'))
def test_load_metadata_with_disabled(self, filemock):
result = load_metadata("john")
self.assertEqual(result,{"disabled":True})
filemock.assert_called_with("john.json")

测试文件的执行结果,令人心碎:

TypeError: the JSON object must be str, bytes or bytearray, not 'MagicMock'

在命令行中执行相同的操作时,给出了成功的结果。

我尝试了几种方法(用 with 打补丁,作为装饰器),但我唯一能想到的是 unittest 库本身,无论它是什么可能会干扰模拟和补丁。

还检查了 virtualenv 和 ipython 中的 python 版本,json 库的版本。

我想知道为什么看起来相同的代码却在一个地方工作并且在另一个中不起作用。或者至少是指向正确方向的指针,以了解为什么会发生这种情况。

最佳答案

json.load() 只是调用 fh.read(),但 fh 不是 mock_open()对象。这是一个 mock_open()() 对象,因为 new_callable 在修补以创建替换对象之前被调用:

>>> from unittest.mock import patch, mock_open
>>> with patch('builtins.open', new_callable=mock_open(read_data='{"disabled":True}')) as filemock:
... with open("john.json") as fh:
... print(fh.read())
...
<MagicMock name='open()().__enter__().read()' id='4420799600'>

不要使用 new_callable,您不希望调用您的 mock_open() 对象!只需将它作为 new 参数传递给 @patch()(这也是第二个位置参数,因此您可以省略 new= 此处):

@patch('builtins.open', mock_open(read_data='{"disabled":True}'))
def test_load_metadata_with_disabled(self, filemock):

当用作 open() 函数时,您可以在其上调用 .read():

>>> with patch('builtins.open', mock_open(read_data='{"disabled":True}')) as filemock:
... with open("john.json") as fh:
... print(fh.read())
...
{"disabled":True}

new 参数是在打补丁时将替换原始对象的对象。如果保留默认值,则使用 new_callable() 代替。您不需要在此处使用 new_callable()

关于python - 使用 mock.patch 和 mock_open 模拟包含 JSON 数据的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54990907/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com