【问题标题】:How to mock class used in separate namespace?如何模拟在单独的命名空间中使用的类?
【发布时间】:2016-09-17 05:55:19
【问题描述】:

包结构:

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

【问题讨论】:

  • Python 支持 Monkey-Patching。您可以简单地调用pqr.pq.Lm = your_mockupAb 将使用your_mockup 而不是原来的Lm。 (这回答了您的问题,但它可能不是测试的最佳模式。考虑修改 Ab 的构造函数以允许传递替代的 Lm 实现作为替代。)
  • @Phillip 谢谢你的回答,但我没有完全明白,你能给我一个工作代码sn-p吗,我是测试框架的新手。

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


【解决方案1】:

Lm 来自哪里并不重要。您将Lm 作为全局there 导入到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

【讨论】:

    【解决方案2】:

    为了进行测试,您可以使用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 创建特定于它们导入的模块的模块对象,因此您需要从pq 模块模拟特定的Lm 对象以测试其功能。该库起初使用起来有点复杂,并且包含的​​信息远远超出单个 StackOverflow 答案中所涵盖的信息,因此我建议您阅读一下。

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

    我本人对mock 库还很陌生,如果我错了,请随时纠正我!

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-07
      • 2023-04-10
      • 1970-01-01
      • 2019-10-23
      • 2015-09-17
      • 2017-01-08
      • 2010-09-12
      • 1970-01-01
      相关资源
      最近更新 更多