174

我想了解如何@patch从导入的模块中获取功能。

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

应用程序/模拟.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"

测试/模拟测试.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. 如何模拟要导入到正在测试的命名空间的其他包中的方法?

4

2 回答 2

229

当您使用包中的patch装饰器时,您是在正在测试的命名空间(在这种情况下)中修补它,而不是从导入函数的命名空间(在这种情况下)。unittest.mockapp.mocking.get_user_nameapp.my_module.get_user_name

要执行您描述的操作,请@patch尝试以下操作:

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')

标准库文档包含一个有用的部分来描述这一点。

于 2013-04-21T18:35:36.790 回答
24

虽然 Matti John 的回答解决了您的问题(也帮助了我,谢谢!),但是,我建议将原始 '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')
于 2015-02-20T12:21:39.207 回答