Как исправить открытие из импортированного модуля с помощью Mock

Я пишу несколько модульных тестов для имеющегося у меня модуля. Мне нужно исправить open, чтобы при вызове функций внутри тестируемого модуля open вместо реального open использовался макет.

Этот код работает, но я думаю, что он сломал бы другие тесты, потому что не восстанавливает open до исходного значения:

class TestCases(unittest.TestCase):
    def test_something(self):
        from amodule import bmodule

        open_mock = mock.MagicMock(spec=open)
        bmodule.__builtins__['open'] = open_mock
        read_mock = mock.MagicMock()
        open_mock.return_value.__enter__.return_value = read_mock

        self.assertTrue(bmodule.some_function())
        self.assertEqual(open_mock.call_args_list, ['filename1', 'filename2'])

Как я могу сделать это с помощью mock.patch?


person Facundo Casco    schedule 22.03.2013    source источник


Ответы (1)


Вместо monkeypatching open в __builtins__, вы можете исправить это в самом bmodule. Преимущество этого в том, что только функции в bmodule получат вашу исправленную открытую функцию. Подробнее об этом можно узнать в фиктивной документации .

Таким образом, вы можете установить свою версию open, используя patch.object в качестве диспетчера контекста:

from mock import patch
class TestCases(unittest.TestCase):
    def test_something(self):
        from amodule import bmodule

        open_mock = mock.MagicMock(spec=open)
        read_mock = mock.MagicMock()
        open_mock.return_value.__enter__.return_value = read_mock
        with patch.object(bmodule, 'open', open_mock, create=True):
            self.assertTrue(bmodule.some_function())
        self.assertEqual(open_mock.call_args_list, ['filename1', 'filename2'])

Оператор with гарантирует, что патч будет удален, когда выполнение выйдет из блока with. Часть create=True необходима, чтобы убедить патч в том, что вы действительно собираетесь создать привязку open в пространстве имен bmodule - это мера предосторожности, чтобы люди случайно не высмеяли неправильное имя, но в вашем случае это необходимо, потому что open живет в __builtins__, а вы хочу привязать его к bmodule.

person babbageclunk    schedule 22.03.2013