【问题标题】:python unittest mock can't handle partially qualified namepython unittest mock无法处理部分限定名
【发布时间】:2016-03-01 01:35:14
【问题描述】:

如果我有两个包含以下内容的文件:

test_helper.py:

class Installer:
    def __init__(self, foo, bar, version):
        # Init stuff
        raise Exception('If we're here, mock didn't work')

    def __enter__(self):
        return self

    def __exit__(self, type, value, tb):
        # cleanup
        pass

    def install(self):
        # Install stuff
        raise Exception('If we're here, mock didn't work')

并且 test.py:

import unittest
from mock import patch
from test_helper import Installer

class Deployer:
    def deploy(self):
        with Installer('foo', 'bar', 1) as installer:
            installer.install()

class DeployerTest(unittest.TestCase):
    @patch('tests.test_helper.Installer', autospec=True)
    def testInstaller(self, mock_installer):
        deployer = Deployer()
        deployer.deploy()
        mock_installer.assert_called_once_with('foo', 'bar', 1)

上面的代码没有正确测试。模拟未正确应用:

  File "/Library/Python/2.7/site-packages/mock-1.3.0-py2.7.egg/mock/mock.py", line 947, in assert_called_once_with
    raise AssertionError(msg)
AssertionError: Expected 'Installer' to be called once. Called 0 times.

如果我在test.py 中进行以下更改:

  1. from test_helper import Installer 更改为import test_helper,然后
  2. with Installer('foo', 'bar', 1) as installer: 更改为with test_helper.Installer('foo', 'bar', 1) as installer:

然后代码就可以工作了。为什么模拟仅在我使用完全限定名称时适用?它应该在部分合格的情况下工作吗?

【问题讨论】:

    标签: python unit-testing mocking python-unittest


    【解决方案1】:

    您正在test.py 中测试您的Deployer 类,它正在调用Installer。这个安装程序是你想要模拟的。所以,你的装饰者应该尊重这一点。

    我不知道你到底是从哪里测试的。但作为一个例子,如果你在与test.py 相同的级别运行测试,那么你可以简单地对你的装饰器执行此操作,它应该可以工作:

    import unittest
    
    from dower import Installer
    from mock import patch
    
    class Deployer:
        def deploy(self):
            with Installer('foo', 'bar', 1) as installer:
                installer.install()
    
    class DeployerTest(unittest.TestCase):
        @patch('test.Installer', autospec=True)
        def testInstaller(self, mock_installer):
            deployer = Deployer()
            deployer.deploy()
            mock_installer.assert_called_once_with('foo', 'bar', 1)
    
    
    if __name__ == '__main__':
        unittest.main()
    

    注意:您不应该在安装程序模块中进行模拟。在这种情况下,您不关心 Installer。只是它返回您的Mock,因此您可以继续测试您的Deployer 的行为。这样想,你就会明白为什么你必须嘲笑你正在测试的东西。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多