如何修补 Python 的 raise(或 return)关键字以进行单元测试?

How to patch Python's raise (or return) keyword for the purpose of unit testing?

mock.patch 能够捕获的 Python 关键字的命名空间是什么?

当有人想打开补丁或打印时,可以使用mock.patch("builtins.open")mock.patch("mymodule.open"),但这不起作用,例如raise

如果我有 raise somemodule.SomeException 语句,那么我可以很容易地测试是否引发了异常,但是我如何断言实际上已经调用了 raise 关键字。喜欢(在 pytestpytest-mock 的帮助下):

def test_myfunction_calls_raise(self, mocker):
    mocked = mocker.patch("mymodule.raise")
    mymodule.myfunction()
    mocked.assert_called_once()

编辑:我有 ,所以 mock.patch 不适用。除此之外,除了明显的解决方案 - 测试结果 - 是否有其他一些有意义的技术来测试代码中是否调用了 Python 关键字(raisereturn、...)?

编辑 2: 我要测试的实际代码(pynput 的 Listener stop() 在 Xfce 中运行不佳,因此我必须引发异常以停止 Listener 线程):

import pynput
# ...

def stop(self):
    """Stops listener by raising an exception."""
    try:
        raise pynput.mouse.Listener.StopException
    except pynput.mouse.Listener.StopException:
        return False

编辑 3:使用以下两种测试方法对上述方法进行了单元测试:

def test_stop_stops_listener(self, mocker):
    """StopException is raised if MagicMock has got StopException attribute."""
    mocked = mocker.patch("pynput.mouse.Listener")
    with pytest.raises(TypeError):  # catching classes that do not inherit from BaseException is not allowed
        base.BaseMouse().stop()
    assert hasattr(mocked, "StopException")

def test_stop_returns_False(self, mocker):
    assert base.BaseMouse().stop() is False

您不能修补关键字。它们是 Python 语法的一部分。当 Python 解释器获取一段 Python 代码时,它会对其进行解析并分几步将其转换为某种内部表示形式 ('bytecode')。然而,字节码与原始源代码不再有直接关系——关键字有 'disappeared'.

相比之下,模块和 class 属性以及它们在代码中的访问仍将在字节码中找到。打补丁基本上就是临时替换这些属性。

或者换句话说,您可以修补属性,但关键字不是属性。