如何使用pytest模拟导入的模块

时间:2018-08-14 22:16:50

标签: python mocking python-unittest

之前曾有人提出过类似的要求,但我一直在努力使其工作。

如何模拟另一个文件中的导入模块

我有一个文件:
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

我像这样设置测试,因为在where to patch中它指定了

  

在这种情况下,我们要在模块上查找要修补的类,因此我们必须修补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

1 个答案:

答案 0 :(得分:1)

此行仅创建一个生成器:

b.get_video_frame('foo')

永远不会到达is_open = vidcap.isOpened()行,因为在测试功能中,生成器在开始时就保持冻结状态,因此副作用永远不会增加。

否则,您将正确使用模拟程序和补丁程序。