Python mock Patch os.environ и возвращаемое значение
Модульное тестирование conn() с использованием mock:
app.py
import mysql.connector
import os,urlparse
def conn():
if 'DATABASE_URL' in os.environ:
url=urlparse(os.environ['DATABASE_URL'])
g.db = mysql.connector.connect(user=url.username,password=url.password, host=url.hostname,database=url.path[1:])
else mysql.connector.error.Errors as err:
return "Error
test.py
def test_conn(self):
with patch(app.mysql.connector) as mock_mysql:
with patch(app.os.environ) as mock_environ
con()
mock_mysql.connect.assert_callled_with("credentials")
Ошибка: утверждение mock_mysql.connect.assert_called_with
не называется.
я полагаю, что это потому, что Database_url отсутствует в моем исправленном os.environ, и из-за этого тестового вызова не выполняется mysql_mock.connect.
Вопросы:
1 Какие изменения мне нужно сделать, чтобы этот тестовый код работал?
2. Нужно ли мне исправлять urlparse?
7 ответов
import mysql.connector
import os,urlparse
@mock.patch.dict(os.environ,{'DATABASE_URL':'mytemp'})
def conn(mock_A):
print os.environ["mytemp"]
if 'DATABASE_URL' in os.environ:
url=urlparse(os.environ['DATABASE_URL'])
g.db = mysql.connector.connect(user=url.username,password=url.password, host=url.hostname,database=url.path[1:])
else mysql.connector.error.Errors as err:
return "Error
Вы можете попробовать это так. Просто позвоните conn
с dummy
аргумент.
Или же
Если вы не хотите изменять исходную функцию, попробуйте это:
def func():
print os.environ["mytemp"]
def test_func():
k=mock.patch.dict(os.environ,{'mytemp':'mytemp'})
k.start()
func()
k.stop()
test_func()
Для этого я обнаружил, что приспособление pytest monkeypatch приводит к лучшему коду, когда вам нужно установить переменные окружения:
def test_conn(monkeypatch):
monkeypatch.setenv('DATABASE_URL', '<URL WITH CREDENTIAL PARAMETERS>')
with patch(app.mysql.connector) as mock_mysql:
conn()
mock_mysql.connect.assert_callled_with(<CREDENTIAL PARAMETERS>)
Принятый ответ правильный. Просто хочу добавить служебную оболочку, чтобы сделать это немного чище.
def mockenv(**envvars):
return mock.patch.dict(os.environ, envvars)
@mockenv(DATABASE_URL="foo", EMAIL="bar@gmail.com")
def test_something():
assert os.getenv("DATABASE_URL") == "foo"
В моем случае использования я пытался имитировать отсутствие установленной переменной окружения. Для этого не забудьте добавить
clear=True
к вашему патчу.
with patch.dict(os.environ, {}, clear=True):
func()
Перед импортом модуля в заголовке файла имитируйте среду:
with patch.dict(os.environ, {'key': 'mock-value'}):
import your.module
Вы также можете использовать что-то вроде modified_environ
Диспетчер контекста опишу в этом вопросе настройки / восстановления переменных среды
with modified_environ(DATABASE_URL='mytemp'):
func()
Небольшое улучшение, чтобы ответить здесь
@mock.patch.dict(os.environ, {"DATABASE_URL": "foo", "EMAIL": "bar@gmail.com"})
def test_something():
assert os.getenv("DATABASE_URL") == "foo"