Python mock Patch os.environ并返回值

时间:2015-07-23 09:01:45

标签: python unit-testing python-3.x dependency-injection mocking

使用mock进行单元测试conn():

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'吗?

6 个答案:

答案 0 :(得分:42)

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()

答案 1 :(得分:8)

为此,我发现pytest's monkeypatch fixture在需要设置环境变量时会产生更好的代码:

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>)

答案 2 :(得分:5)

接受的答案是正确的。这是装饰器@mockenv要做的。

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"

答案 3 :(得分:3)

在我的用例中,我试图模拟没有设置环境变量。为此,请确保将 clear=True 添加到补丁中。

with patch.dict(os.environ, {}, clear=True):
    func()

答案 4 :(得分:2)

您还可以使用此question中描述的modified_environ上下文管理器来设置/恢复环境变量。

with modified_environ(DATABASE_URL='mytemp'):
    func()

答案 5 :(得分:2)

在导入模块之前在文件模拟环境的头部:

with patch.dict(os.environ, {'key': 'mock-value'}):
    import your.module
相关问题