简体   繁体   English

python unittest模拟不能处理部分合格的名称

[英]python unittest mock can't handle partially qualified name

If I have two files with the following contents: 如果我有两个具有以下内容的文件:

test_helper.py : 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')

And test.py : 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)

The code above doesn't test correctly. 上面的代码无法正确测试。 The mock is not applied properly: 模拟无法正确应用:

  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.

If I make the following changes in test.py : 如果我在test.py进行以下更改:

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

The code then works. 该代码然后工作。 Why does the mock only apply when I use the fully qualified name? 为什么仅当我使用完全限定名称时才适用该模拟? Is it supposed to work in the partially-qualified case? 它应该在部分合格的情况下起作用吗?

You are testing your Deployer class inside test.py , which is calling Installer . 您正在test.py (正在调用Installer中测试Deployer类。 This installer is what you want to mock. 该安装程序是您要模拟的。 So, your decorator should be with respect to that. 因此,您的装饰者应对此有所重视。

I don't know where you are testing from exactly. 我不知道您到底在哪里测试。 But as an example, if you are running your test from the same level as test.py , then you can simply do this to your decorator and it should work: 但以一个示例为例,如果您从与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()

Note: You should not be mocking within the Installer module. 注意:您不应该在Installer模块内进行嘲笑。 You don't care about Installer in this case. 在这种情况下,您无需关心 Installer。 Just that it returns your Mock , so you can continue testing the behaviour of your Deployer . 只是它返回了您的Mock ,因此您可以继续测试Deployer的行为。 Think of it that way, and you will realize why you have to mock with respect to what you are testing. 以这种方式思考,您将意识到为什么必须针对测试内容进行嘲笑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM