Используя фреймворк Python Unittest, как вы имитируете или заменяете модуль, код которого запускается при загрузке модуля?
Я понимаю, что это плохо написанный код, но это похоже на то, что мне нужно протестировать. (См. Пример)
Я понимаю, что как только модуль импортирован, его можно исправить, чтобы использовать макеты. Но что, если есть код, который запускается немедленно?
У меня есть файл, который нужно протестировать. Один из импортируемых файлов запускает код немедленно, см. Пример.
file_under_test.py
from somewhere.something.worker import a_func as f
class ClassToTest():
__init__(self):
...
модульwhere.something.worker
import os
import redis
REDIS_HOST = os.environ.get('redishost', '') #<-- Mock this
connection = redis.Redis(host=REDIS_HOST) #<--- Mock this
class AClass():
...
def a_func():
connection.doSomething()
...
По крайней мере, добавьте в модуль функцию init_connection()
, чтобы отложить создание соединения до тех пор, пока вы не будете готовы к установке соединения.
@chepner, я тоже об этом подумал ... переписать.
Отложите создание соединения до тех пор, пока вы действительно не будете готовы к тому, чтобы это произошло. В качестве бонуса вы можете заставить init_connection
использовать дополнительное заранее выделенное соединение, а не всегда создавать его по запросу. Это упрощает переход к тому, чтобы полностью отказаться от глобального подключения.
import os
import redis
connection = None
def init_connection(c=None):
global connection
if connection is None:
if c is None:
c = redis.Redis(host=os.environ.get('redishost', ''))
connection = c
...
Затем в своем тестовом модуле вы можете вызвать init_connection
изнутри setupModule
с возможностью передачи желаемого объекта, подобного соединению.
вместо того, чтобы что-либо исправлять.
def setupModule():
init_connection()
# or
# conn = Mock()
# ... configure the mock ...
# init_connection(conn)
class ClassToTest():
__init__(self):
...
Это то, что я решил сделать. Мне просто интересно, есть ли другой способ :-(
Даже если бы есть является по-другому, я бы все равно провел рефакторинг.
Я бы посчитал, что код не прошел любой тест, который вы имели в виду, и потребовал бы его рефакторинга, чтобы избежать открытия соединения сразу после импорта.
a_func
должен принимать соединение в качестве аргумента или быть методом класса, для которого пример задано соединение.