Python 模拟来自导入模块的函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16134281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 21:50:32  来源:igfitidea点击:

Python Mocking a function from an imported module

pythonunit-testingpython-unittestpython-mock

提问by nsfyn55

I want to understand how to @patcha function from an imported module.

我想了解如何@patch从导入的模块中调用函数。

This is where I am so far.

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

app/mocking.py:

应用程序/模拟.py:

from app.my_module import get_user_name

def test_method():
  return get_user_name()

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

app/my_module/__init__.py:

应用程序/my_module/__init__.py:

def get_user_name():
  return "Unmocked User"

test/mock-test.py:

测试/模拟测试.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()

This does notwork as I would expect. The "patched" module simply returns the unmocked value of get_user_name. How do I mock methods from other packages that I am importing into a namespace under test?

这并没有工作,我期望的那样。“修补”模块只返回get_user_name. 我如何模拟我正在导入到被测命名空间的其他包中的方法?

采纳答案by Matti John

When you are using the patchdecorator from the unittest.mockpackage you are notpatching the namespace the module is imported from (in this case app.my_module.get_user_name) you are patching it in the namespace under test app.mocking.get_user_name.

当您使用包中的patch装饰器时,unittest.mock不是在修补导入模块的命名空间(在这种情况下app.my_module.get_user_name),而是在被测命名空间中修补它app.mocking.get_user_name

To do the above with Mocktry something like the below:

要执行上述操作,请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')

The standard library documentation includes a useful sectiondescribing this.

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

回答by Tgilgul

While Matti John's answer solves your issue (and helped me too, thanks!), I would, however, suggest localizing the replacement of the original 'get_user_name' function with the mocked one. This will allow you to control when the function is replaced and when it isn't. Also, this will allow you to make several replacements in the same test. In order to do so, use the 'with' statment in a pretty simillar manner:

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