将 Pytest 模拟值设置为 None

Set Pytest mock value to None

我有一个 main.py 文件,其中包含 WindoMgr class、xvfb作为一个class属性和两个class方法_cleanup_lock_filefunc_to_test。我只有在测试 else 块时遇到问题,当 cls.xvfbNone[ 时会触发该块=40=]。 else 块 returns b 的默认值是 1.

#main.py
class WindowMgr:
    xvfb = None

    @classmethod
    def _cleanup_lock_file(cls):
        return True

    @classmethod
    def func_to_test(cls):
        b = 1
        if cls.xvfb is not None:
            print(cls.xvfb)  #<MagicMock name='xvfb' id='61908568'>
            try:
                cls.xvfb.terminate()
                b = 2
            except Exception:
                b = 1 + 2
            finally:
                cls._cleanup_lock_file()
        else:
            return b
        return b

现在,在 test_main.py 文件中,我已将 xvfb 修补为在 try 块中模拟 cls.xvfb.terminate(),但我想要cls.xvfbNone 以触发 else 块。我试过 xvfb = Nonexvfb.return_value = None 之类的东西。但是 else 块不会被触发,因为打印 cls.xvfb 将其显示为代码中注释掉的 MagickMock 对象。 WindowMgr.func_to_test() return 值是 2 而不是 1。它应该 return 默认值 b 为 1。 如何将 cls.xvfb 模拟对象设置为 None?任何帮助将不胜感激。

#test_main.py
from main import WindowMgr

def test_main_func(mocker):
    xvfb = mocker.patch.object(WindowMgr, 'xvfb')

    # To test the else block
    # xvfb = None -----> doesn't work
    # xvfb.return_value = None ----> doesn't work

    assert WindowMgr.func_to_test() == 1   # AssertionError: assert 2 == 1

问题是设置 xvbf 只会重新分配局部变量,而不是模拟变量(这只是正常的 Python 行为)。设置 return_value 不起作用,因为 xvbf 不是可调用的。但是,如果您使用 property mock 而不是常规模拟,它的行为就像是可调用的,并且可以通过 return_value:

设置值
def test_main_func(mocker):
    xvfb = mocker.patch.object(WindowMgr, "xvfb",
                               new_callable=mocker.PropertyMock)
    xvfb.return_value = None

    assert WindowMgr.func_to_test() == 1

(为了方便,您可以直接从 mocker 访问 PropertyMock

即使 xvbf 是一个 class 变量而不是 属性,从模拟的角度来看,它的行为类似于 属性,这将起作用。