Python издевается над функцией из импортированного модуля


Я хочу понять как @patch функция из импортированного модуля.

вот где я нахожусь до сих пор.

app/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()

app/my_module/__init__.py:

def get_user_name():
  return "Unmocked User"

test/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. Как я могу издеваться над методами из другие пакеты, которые я импортирую в тестируемое пространство имен?

2 59

2 ответа:

когда вы используете 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')

стандартная библиотечная документация включает в себя полезный раздел описывая это.

в то время как ответ Матти Джона решает вашу проблему (и помог мне тоже, спасибо!), Я бы, однако, предложил локализовать замену исходной функции "get_user_name" на издевательскую. Это позволит вам контролировать, когда функция заменить, а когда это не так. Кроме того, это позволит вам сделать несколько замен в один и тот же тест. Для того, чтобы сделать это, используйте' с ' statment в довольно похожей манере:

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