Резюме: когда импортируется определенный модуль python, я хочу иметь возможность перехватить это действие, и вместо загрузки требуемого класса я хочу загрузить другой класс по своему выбору.
Причина: я работаю над устаревшим кодом. Мне нужно написать некоторый код модульного теста, прежде чем я начну улучшать / реорганизовывать. Однако код импортирует определенный модуль, который не будет работать в настройках модульного теста. (Из-за зависимости сервера базы данных)
Псевдо-код:
from LegacyDataLoader import load_me_data
...
def do_something():
data = load_me_data()
Таким образом, в идеале, когда python оправдывает строку импорта выше в модульном тесте, вместо него загружается альтернативный класс, говорит MockDataLoader.
Я все еще использую 2.4.3. Я полагаю, есть хук импорта, которым я могу манипулировать
Редактировать
Спасибо большое за ответы. Все они очень полезны.
Один конкретный тип предположений касается манипуляции с PYTHONPATH. Это не работает в моем случае. Так что я подробно остановлюсь здесь.
Исходная кодовая база организована таким образом
./dir1/myapp/database/LegacyDataLoader.py
./dir1/myapp/database/Other.py
./dir1/myapp/database/__init__.py
./dir1/myapp/__init__.py
Моя цель - улучшить класс Other в модуле Other. Но так как это устаревший код, я не чувствую себя комфортно, работая над ним, не привязав сначала к нему набор тестов.
Теперь я ввожу код этого юнит теста
./unit_test/test.py
Содержание просто:
from myapp.database.Other import Other
def test1():
o = Other()
o.do_something()
if __name__ == "__main__":
test1()
Когда CI-сервер запускает вышеуказанный тест, тест не пройден. Это связано с тем, что класс Other использует LegacyDataLoader, а LegacydataLoader не может установить соединение базы данных с сервером БД из поля CI.
Теперь давайте добавим поддельный класс, как предложено:
./unit_test_fake/myapp/database/LegacyDataLoader.py
./unit_test_fake/myapp/database/__init__.py
./unit_test_fake/myapp/__init__.py
Измените PYTHONPATH на
export PYTHONPATH=unit_test_fake:dir1:unit_test
Теперь тест не пройден по другой причине
File "unit_test/test.py", line 1, in <module>
from myapp.database.Other import Other
ImportError: No module named Other
Это как-то связано с тем, как python разрешает классы / атрибуты в модуле