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"
Другие вопросы по тегам