2013-04-21 109 views
46

我想了解如何从导入的模块导入功能@patchPython嘲笑导入模块的功能

这是我到目前为止的地方。

应用程序/ mocking.py:

from app.my_module import get_user_name 

def test_method(): 
    return get_user_name() 

if __name__ == "__main__": 
    print "Starting Program..." 
    test_method() 

应用程序/ my_module/__ init__.py:

def get_user_name(): 
    return "Unmocked User" 

测试/ mock-test.py:

import unittest 
from app.mocking import test_method 

def mock_get_user(): 
    return "Mocked This Silly" 

@patch('app.my_module.get_user_name') 
class MockingTestTestCase(unittest.TestCase): 

    def test_mock_stubs(self, mock_method): 
    mock_method.return_value = 'Mocked This Silly') 
    ret = test_method() 
    self.assertEqual(ret, 'Mocked This Silly') 

if __name__ == '__main__': 
    unittest.main() 

这是不是工作正如我所料。 “修补”模块只是返回get_user_name的解锁值。如何从我导入到测试中的命名空间的其他软件包中模拟方法?

+1

问题是关于“嘲笑最佳实践”或者您所做的事情是否合理?关于第一个我会说使用一个模拟库,例如['Mock'](http://www.voidspace.org.uk/python/mock/),它包含在python3.3 +中['unittest .mock'](http://docs.python.org/dev/library/unittest.mock)。 – Bakuriu 2013-04-21 17:55:15

+0

我在问我是否正在讨论这项权利。我看了莫克,但我没有看到解决这个问题的方法。有什么方法可以重新创建我在Mock上面做的事情? – nsfyn55 2013-04-21 18:00:09

回答

66

当您使用的patch装饰从unittest.mock包您修补模块从(在这种情况下app.my_module.get_user_name)您已被测app.mocking.get_user_name修补它在名称空间导入的命名空间。

要做到以上Mock你可以试试下面的:

from mock import patch 
from app.mocking import test_method 

class MockingTestTestCase(unittest.TestCase): 

    @patch('app.mocking.get_user_name') 
    def test_mock_stubs(self, test_patch): 
     test_patch.return_value = 'Mocked This Silly' 
     ret = test_method() 
     self.assertEqual(ret, 'Mocked This Silly') 

标准库文件包含有用section描述此。

+0

这会导致我的问题。 'get_user_name'与'test_method'不在一个模块中。有没有办法在sub_module中模拟一些东西?我在下面以丑陋的方式修复它。 – nsfyn55 2013-04-21 19:11:06

+4

由于您将函数导入到'app.mocking'中,因此'get_user_name'与'test_method'不在一个模块中,因为它们位于相同的名称空间中。 – 2013-04-21 19:22:33

+0

得到了雅。是的,这工作表示感谢! – nsfyn55 2013-04-21 19:24:00

5

虽然马蒂约翰的答案解决了您的问题(也帮助了我,谢谢!),但是,我会建议本地化替换原来的'get_user_name'函数与嘲弄的。这将允许您控制何时更换功能以及何时不更换功能。此外,这将允许您在同一测试中进行多次替换。为了做到这一点,请以相当相似的方式使用'with'语句:

from mock import patch 

class MockingTestTestCase(unittest.TestCase): 

    def test_mock_stubs(self): 
     with patch('app.mocking.get_user_name', return_value = 'Mocked This Silly'): 
      ret = test_method() 
      self.assertEqual(ret, 'Mocked This Silly') 
+0

这对于提出的问题来说是不重要的。无论是使用'patch'作为装饰器还是上下文管理器都是特定于用例的。例如,你可以使用'patch'作为装饰器来模拟'xunit'或'pytest'类中所有测试的值,而在其他情况下,它有用于具有由上下文管理器提供的细粒度控制。 – nsfyn55 2015-07-20 17:35:43