我正在尝试模拟一个在导入所述类的模块中调用的类,我想测试该类。
# application.py
from my_module.my_submodule import MyClass
def my_function(var1):
instance = MyClass()
instance.some_function(var1)
Run Code Online (Sandbox Code Playgroud)
和我的测试文件
# 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()
Run Code Online (Sandbox Code Playgroud)
这给出了一个错误,说MockClass没有被调用。
现在,通过查看这个问题:为什么 python 模拟补丁不起作用?,我受到启发,将application.py导入更改为此
# application.py
import my_module.my_submodule as mysub
def my_function(var1):
instance = mysub.MyClass()
instance.some_function(var1)
Run Code Online (Sandbox Code Playgroud)
也就是说,我不直接导入我想要在测试中模拟的类。现在可以了。
我的问题是,这是否按预期工作,或者我以原来的方式做错了什么?如果我想模拟我想要测试的模块中使用的类,是否真的有必要始终像这样导入模块?
是的,它正在按预期工作,但您修补了错误的目标。尝试打补丁application.MyClass。
application没有my_module.my_submodule.MyClass在任何地方使用,而是MyClass使用别名。
不,您不必以某种特定方式导入模块即可模拟/修补某些名称。您所要做的就是查看该名称在运行时如何使用(当您想要修补它时)。
如果测试位于与正在测试的模块不同的模块中,并且application在这种情况下,被测试的模块导入名称并像 in 一样直接使用它from a import MyClass,然后在测试模块中导入application并修补application.MyClass。如果改为application使用import athen 调用,则a.MyClass()必须修补application.a.MyClass。
因此,您可以使补丁目标适应模块中的具体命名场景application。例如,如果您的测试位于同一application模块中,并且该类被用作MyClass,则您需要修补__main__.MyClass。
然而,确实,以某些方式编写代码可以使测试时更容易修补。一个很好的例子是当要模拟的实体是函数参数时。只需使用模拟参数调用该函数即可。
如果您发现修补过于复杂或看起来不可能,请尝试重写应用程序中的代码,使其更“可测试”。
作为参考的另一个示例,请参阅修补位置