python - 如何使用 pytest 模拟导入的模块
问题描述
以前有人问过类似的问题,但我很难让它发挥作用。
如何从另一个文件模拟导入模块
我有一个文件:(
b.py
命名为与链接的文档一致)
import cv2 # module 'a' in the linked docs
def get_video_frame(path):
vidcap = cv2.VideoCapture(path) # `a.SomeClass` in the linked docs
vidcap.isOpened()
...
test_b.py
import b
import pytest # with pytest-mock installed
def test_get_frame(mocker):
mock_vidcap = mocker.Mock()
mock_vidcap.isOpened.side_effect = AssertionError
mock_cv2 = mocker.patch('cv2.VideoCapture')
mock_cv2.return_value = mock_vidcap
b.get_video_frame('foo') # Doesn't fail
mock_vidcap.isOpened.assert_called() # fails
我这样设置测试是因为在哪里修补它指定如果
在这种情况下,我们要修补的类正在 a 模块上查找,因此我们必须修补 a.SomeClass :
@patch(‘a.SomeClass’)
我尝试了一些其他的修补组合,但它表现出相同的行为,这表明我没有成功修补模块。如果要应用补丁程序b.get_video_frame('foo')
将失败,因为side_effect
; assert_called
失败了,支持这个。
编辑以减少我离开其余部分的问题的长度get_video_frame
。不幸的是,我们留下的部分是关键部分。完整的功能是:
def get_video_frame(path):
vidcap = cv2.VideoCapture(path) # `a.SomeClass` in the linked docs
is_open = vidcap.isOpened()
while True:
is_open, frame = vidcap.read()
if is_open:
yield frame
else:
break
解决方案
这一行只创建了一个生成器:
b.get_video_frame('foo')
这条线is_open = vidcap.isOpened()
永远不会到达,因为在测试功能中,生成器在开始时保持冻结,因此副作用永远不会出现。
否则,您将正确使用嘲笑器和补丁。
推荐阅读
- php - 在未知迭代的循环后关闭最后一个 div(逻辑问题)
- symfony - 更改教义/symfony 中的默认字符串长度
- pandas - 使用 pandas 加入具有不同列的 2 个多索引数据帧
- python - 查找对数组进行排序所需的最小交换次数的算法不正确
- android - 材质收藏按钮与图像按钮
- rust - 为什么一个 Cargo 包只能有一个库目标?
- java - 为什么LinkedBlockingQueue的put()中有一个while循环
- graphics - SPSS:如何以有组织的方式显示自定义数据
- google-sheets - 根据多个条件更新列参考另一个工作簿
- javascript - 数据表插件未运行