python - 在 Python 中模拟导入的类
问题描述
我正在尝试模拟一个在导入我想要测试的类的模块中调用的类。
# application.py
from my_module.my_submodule import MyClass
def my_function(var1):
instance = MyClass()
instance.some_function(var1)
和我的测试文件
# test_application.py
import mock
import application
def test_my_function():
with mock.patch('my_module.my_submodule.MyClass') as MockClass:
application.my_function(var1)
MockClass.assert_called()
这给出了一个错误说MockClass
没有被调用。
现在,通过查看这个问题:为什么 python 模拟补丁不起作用?,我受到启发将application.py
导入更改为此
# application.py
import my_module.my_submodule as mysub
def my_function(var1):
instance = mysub.MyClass()
instance.some_function(var1)
也就是说,我不直接导入要在测试中模拟的类。现在它起作用了。
我的问题是,如果这是按预期工作,还是我以原始方式做错了什么?如果我想模拟要测试的模块中使用的类,是否真的有必要总是导入这样的模块?
解决方案
是的,它按预期工作,但是您修补了错误的目标。尝试打补丁application.MyClass
。
application
不在my_module.my_submodule.MyClass
任何地方使用,而是使用MyClass
别名。
不,您不必以某种特定方式导入模块即可模拟/修补某些名称。您需要做的是查看该名称在运行时是如何使用的,何时需要对其进行修补。
如果测试与正在测试的模块位于单独的模块中,并且application
在这种情况下,被测试的模块会导入名称并直接使用它,就像 in 一样from a import MyClass
,那么在测试模块中导入application
和修补application.MyClass
。如果改为application
使用import a
然后调用,则a.MyClass()
必须修补application.a.MyClass
.
因此,您可以使补丁目标适应application
模块中的具体命名场景。例如,如果您的测试在同一个application
模块中,并且该类被用作MyClass
,则需要修补__main__.MyClass
.
然而,以某种方式编写代码可以使您在测试时更容易打补丁,这是事实。一个很好的例子是当要模拟的实体是一个函数参数时。只需使用模拟参数调用该函数。
如果您发现修补过于复杂或看起来不可能,请尝试重写应用程序中的代码,使其更“可测试”。
有关另一个示例作为参考,请参阅修补位置
推荐阅读
- spring - 在 Spring Boot 中单击提交按钮后结果页面未出现
- java - webstart-maven-plugin 自定义 jnlp 模板变量列表
- postgresql - 在 Postgres SQL 中进行并行处理时出现“错误:无法识别的配置参数“max_parallel_workers_per_gather”
- javascript - 多个查询nodejs mysql
- sql - 两个表之间的递归
- c# - 值不会传递 - 只传递空值,并更新网格中的值
- java - 可以关闭()光标对象然后为其设置新值吗?
- lazy-loading - 存储库模式:我们如何从大型数据库中加载一堆数据?
- python - Sklearn:从相互独立的多类分类中获取概率
- android - 使用 Android 意图打开 PDF 文件