简体   繁体   English

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

[英]How to mock an imported module with pytest

Something similar has been asked before, but I'm struggling to get this to work.之前有人问过类似的问题,但我正在努力让它发挥作用。

How do I mock an import module from another file如何从另一个文件模拟导入模块

I have one file:我有一个文件:
b.py (named to be consistent with the linked docs) 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 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

I set the tests up like this because in where to patch it specifies that if我像这样设置测试,因为在修补的位置它指定如果

In this case the class we want to patch is being looked up on the a module and so we have to patch a.SomeClass instead:在这种情况下,我们要修补的类正在 a 模块上查找,因此我们必须修补 a.SomeClass:

@patch(‘a.SomeClass’)

I've tried a few other combinations of patching, but it exhibits the same behavior, which suggests I'm not successfully patching the module.我尝试了其他几种修补组合,但它表现出相同的行为,这表明我没有成功修补模块。 If the patch were to be applied b.get_video_frame('foo') would fail due to the side_effect ;如果要应用补丁b.get_video_frame('foo')将由于side_effect失败; having assert_called fail, supports this.assert_called失败,支持这一点。

Edit in an effort to reduce the length of the question I left off the rest of get_video_frame .编辑以减少问题的长度,我忽略了get_video_frame的其余部分。 Unfortunitly, the parts left off we're the critical parts.不幸的是,剩下的部分我们是关键部分。 The full function is:完整的功能是:

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

This line just creates a generator:这一行只是创建了一个生成器:

b.get_video_frame('foo')

The line is_open = vidcap.isOpened() is never reached, because in the test function the generator remains frozen at the start, therefore the side effect never raises.永远不会到达is_open = vidcap.isOpened()行,因为在测试函数中,生成器在开始时保持冻结状态,因此副作用永远不会增加。

You are otherwise using mocker and patch correctly.否则,您将正确使用 mocker 和 patch。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM