python - 使用 mock.patch 和 mock_open 模拟包含 JSON 数据的文件
问题描述
我正在尝试测试一种需要json.load
在 Python 3.6 中使用的方法。经过几次尝试,我尝试“正常”运行测试(使用 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):
此时您可以.read()
在用作open()
函数时调用它:
>>> 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()
在这里。
推荐阅读
- directshow - Microsoft 的 MPEG-2 解复用器过滤器 - 我可以在图形运行时更改基本流引脚的 PID 吗?
- kotlin - 如何运行 Swagger Codegen 生成的 Kotlin 服务器?
- c++ - QLabel 不使用 QToolButton 显示图像
- java - 安卓电报客户端:如何获取最后一条消息?
- javascript - 基于对象数组验证相同的值
- html - 右侧页面底部的空白区域,左侧正确填充背景色
- apache-spark - 数据类型转换火花数据框列 - pyspark
- r - R - 使用向量作为函数的默认参数列表
- c - 字符串链表的插入排序
- java - 如何修改 REST API 的 Spring 存储库搜索的页面类型结果?