Python 如何模拟在单独命名空间中使用的类?
包结构:Python 如何模拟在单独命名空间中使用的类?,python,python-2.7,namespaces,mocking,python-unittest,Python,Python 2.7,Namespaces,Mocking,Python Unittest,包结构: pqr/pq.py test.py pqr/pq.py具有以下结构 from pqr.pq import Ab 其中lmn是全局安装的pip模块 pq.py的结构 from lmn import Lm class Ab(): def __init__(self): self.lm = Lm() def echo(self, msg): print msg test.py具有以下结构 from pqr.pq import Ab
pqr/pq.py
test.py
pqr/pq.py
具有以下结构
from pqr.pq import Ab
其中lmn是全局安装的pip模块
pq.py的结构
from lmn import Lm
class Ab():
def __init__(self):
self.lm = Lm()
def echo(self, msg):
print msg
test.py
具有以下结构
from pqr.pq import Ab
如何在这里模拟Lm()
类,以便测试Ab类中的所有方法?其实Lm
来自何处并不重要。您将Lm
作为全局名称导入到pqr.pq
命名空间中,因此您只需要在那里替换该名称,而不需要在其他地方替换该名称。这是因为Ab.\uuu init\uu
方法将在自己的模块中“本地”查找它
因此,使用该命令,您只需修补名称pqr.pq.Lm
:
import mock
from pqr.pq import Ab
with mock.patch('pqr.pq.Lm') as mock_lm:
# within this block, `Lm` in the `pqr.pq` namespace has been replaced
# by a mock object
test_instance = Ab()
# assert that the patch succeeded; .return_value is used because
# Ab.__init__ *calls* Lm()
assert test_instance.lm is mock_lm.return_value
另请参阅mock
文档的第页。对于测试,您可以使用mock
模块(在较新的python 3中是标准的,对于较旧的版本,可以从pypi下载)来创建“假”类。有一篇关于模拟库的文章解释了如何做到这一点,我将链接这篇文章,这对我帮助很大。您希望您的test.py文件看起来像下面的代码
from pqr import pq
import mock
class TestLm(unittest.Testcase):
@mock.patch(pq.LM)
def test_lm(self, mock_lm):
my_ab = pq.AB()
my_ab.echo()
使用mock
模块,您可以创建一个模块/类的模拟版本,您可以将其用于测试方法,只需在测试方法上方使用装饰器“修补”它即可。这将使用MagicMock对象替换指定模块/类的原始版本,然后将该对象作为第二个参数传递到测试方法中。这个MagicMock实际上并不执行Lm
的任何功能,但允许您断言它应该如何工作。如果需要,您可以稍后重写功能。然而,有一个陷阱,我链接的指南对此进行了解释。您需要确保从使用Lm的模块导入,而不是以传统方式导入。对于导入,Python创建特定于导入到的模块的模块对象,因此,您需要模拟来自pq
模块的特定Lm
对象,以测试其功能。这个库一开始使用起来有点复杂,包含的信息远远超过了一个简单答案所能涵盖的范围,所以我建议大家阅读一下
可以找到mock
模块的文档。
可以找到Python2.7版本的下载
我本人对mock
库相当陌生,如果我错了,请随时纠正我
编辑:看到Martijn的答案后,我意识到我忘记了my_ab构造函数中的括号 Python支持猴子补丁。您只需调用pqr.pq.Lm=your_mockup
,Ab
将使用your_mockup
而不是原始的Lm
。(这回答了您的问题,但它可能不是最好的测试模式。考虑修改<代码> AB < /代码>的构造函数以允许另一个代码> LM< <代码>实现作为备选方案。)菲利浦谢谢您的回答,但我没有完全理解它,您能给我一个工作代码片段吗?我是测试框架的新手。