Я хочу протестировать модуль Python, который, в свою очередь, зависит от другого модуля Python, который, в свою очередь, ведет себя плохо: он не проверяет __name__
, но всегда выполняет некоторый код. Этот код обращается к файловой системе и, следовательно, мешает модульному тестированию.
Вот упрощенная версия проблемы, которая просто печатает что-то:
test.py:
from unittest import TestCase
import tested
class MyTest(TestCase):
def test_one(self, mocked_dep):
self.assertEqual(1, tested.one())
if __name__ == '__main__':
import unittest
unittest.main()
Тестируемый код, test.py:
import dep
def one():
return 1
Зависимость с плохим поведением, dep.py:
def do_stuff():
# access file system, open network connection, go to database
print("I got called!")
do_stuff()
Когда я запускаю это, я вижу напечатанное сообщение.
I got called!
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Как я могу предотвратить do_stuff
из запущенного?
Я пытался его смоделировать, но к тому времени, когда мой @patch
был оценен с import tested
в начале test.py, модуль, вероятно, уже загружен и do_stuff
имеет был вызван.
Я также пытался import tested
после @patch
внутри теста (удаляя import tested
в строке 3), но он все еще вызывал do_stuff
и печатал его вывод.
from unittest import TestCase
from mock import patch
class MyTest(TestCase):
@patch("tested.dep.do_stuff") # <-- too late? still prints
def test_one(self, mocked_dep):
import tested # <-- moving the import here did not help either
self.assertEqual(1, tested.one())
Я не могу изменить поведение dep.py
, так как от него может зависеть слишком много другого кода.
Как я могу предотвратить вызов do_stuff
? Или это единственный вариант для насмешки над функциями, которые я не хочу вызывать do_stuff
, в данном случае print
?