source

Python mock Patchos.environ 및 반환 값

lovecheck 2023. 5. 12. 22:23
반응형

Python mock Patchos.environ 및 반환 값

모의 실험을 사용하여 장치 테스트 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:
        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_myslog.connect에 대한 테스트 호출이 이루어지지 않습니다.

질문:

  1. 이 테스트 코드가 작동하려면 어떤 변경이 필요합니까?

  2. 패치도 적용해야 합니까?urlparse?

unittest.mock.patch.dict 솔루션을 사용해 볼 수 있습니다.그냥 전화하세요.conn와 함께dummy인수:

import mysql.connector
import os, urlparse
from unittest import mock


@mock.patch.dict(os.environ, {"DATABASE_URL": "mytemp"}, clear=True)  # why need clear=True explained here https://stackoverflow.com/a/67477901/248616
# If clear is true then the dictionary will be cleared before the new values are set.
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:
        return "Error"

또는 원래 기능을 수정하지 않으려면 다음 솔루션을 사용해 보십시오.

import os
from unittest import mock

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 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_called_with(<CREDENTIAL PARAMETERS>)

받아들여진 답이 맞습니다.여기 장식가가 있습니다.@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"

제 사용 사례에서는 환경 변수가 설정되지 않은 것을 조롱하려고 했습니다.이 작업을 수행하려면 다음을 추가해야 합니다.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"

언급URL : https://stackoverflow.com/questions/31582750/python-mock-patch-os-environ-and-return-value

반응형