python - 为了单元测试的目的,如何修补 Python 的 raise(或 return)关键字?
问题描述
mock.patch 能够捕获的 Python 关键字的命名空间是什么?
当有人想打补丁打开或打印然后mock.patch("builtins.open")
或mock.patch("mymodule.open")
可以使用,但这不起作用,例如,使用raise
.
如果我有raise somemodule.SomeException
声明,那么我可以很容易地测试是否引发了异常,但是我如何断言实际上已经调用了 raise 关键字。pytest
喜欢(在和的帮助下pytest-mock
):
def test_myfunction_calls_raise(self, mocker):
mocked = mocker.patch("mymodule.raise")
mymodule.myfunction()
mocked.assert_called_once()
编辑:我有一个很好的答案,所以 mock.patch 不适用。除此之外,除了明显的解决方案(测试结果)之外,是否还有其他有意义的技术来测试代码中是否调用了Python 关键字 ( raise
, , ...)?return
编辑 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 代码时,它会对其进行解析并分几步将其转换为某种内部表示(“字节码”)。然而,字节码与原始源代码不再有直接关系——关键字已经“消失”。
相反,模块和类属性以及它们在代码中的访问仍然可以在字节码中找到。打补丁基本上就是临时替换这些属性。
或者,换一种说法,您可以修补属性,但关键字不是属性。
推荐阅读
- css - 在 css 中将多个 id 与单个类合并的最佳实践是什么?
- visual-studio-code - 扩展如何获取当前连接的远程服务器中文件的远程 URL?
- php - PHP - 验证空表单字段的问题
- php - 如何在回声下使用这个 if 条件?
- mpi - MPI_OP_Create 函数
- php - 为什么我的测验不与 mysql 数据库交互?
- powershell - Powershell 脚本,它将使用正则表达式搜索文件夹并删除早于 XX 的文件
- babylonjs - 在 babylon.js 中为 3d 模型添加按钮
- sql-server - Liquibase generateChangeLog 抛出异常:SQLServerException: Cannot resolve the collation conflict between ... in the INTERSECT operation
- python - 如何在由任意函数创建的 seaborn 散点图中添加一条线