如何模拟在单独的命名空间中使用的类?

时间:2016-09-17 05:55:20

标签: python python-2.7 namespaces mocking python-unittest

包装结构:

pqr/pq.py
test.py

pqr/pq.py具有以下结构

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类中的所有方法?

2 个答案:

答案 0 :(得分:5)

Lm来自哪里并不重要。您已将Lm导入pqr.pq命名空间作为全局那里,因此您只能在那里替换该名称,而不是其他地方。那是因为Ab.__init__方法会在它自己的模块中“本地”查找它。

因此,使用mock library所有您需要做的就是修改名称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文档的Where to patch section

答案 1 :(得分:0)

对于测试,您可以使用mock模块(较新的python 3中的标准,可从旧版本的pypi下载)来创建“假”类。模拟库上有一篇很棒的文章解释了如何做到这一点,我将链接here,这对我帮助很大。您将希望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会创建特定于模块的模块对象。导入到,因此您需要模拟Lm模块中的特定pq对象以测试其功能。该库最初使用起来有点复杂,并且包含的​​信息远远多于单个StackOverflow答案所涵盖的信息,因此我建议您进行一些阅读。

可以找到mock模块的文档here。 可以找到Python 2.7版本的下载here

我自己是mock图书馆的新手,如果我错了,请随时纠正我!

编辑:看到Martijn的回答后,我意识到我忘记了my_ab构造函数中的括号!