簡體   English   中英

如何測試可以使用環境變量初始化的數據類?

[英]How to test dataclass that can be initialized with environment variables?

我有以下數據類:

import os
import dataclasses

@dataclasses.dataclass
class Example:
    host: str = os.environ.get('SERVICE_HOST', 'localhost')
    port: str = os.environ.get('SERVICE_PORT', 30650)

我該如何為此編寫測試? 我嘗試了以下看起來應該可以工作的方法:

from stackoverflow import Example
import os


def test_example(monkeypatch):
    # GIVEN environment variables are set for host and port
    monkeypatch.setenv('SERVICE_HOST', 'server.example.com')
    monkeypatch.setenv('SERVICE_PORT', '12345')
    #   AND a class instance is initialized without specifying a host or port
    example = Example()
    # THEN the instance should reflect the host and port specified in the environment variables
    assert example.host == 'server.example.com'
    assert example.port == '12345'

但這失敗了:

====================================================================== test session starts ======================================================================
platform linux -- Python 3.8.12, pytest-7.1.2, pluggy-1.0.0
rootdir: /home/biogeek/tmp
collected 1 item                                                                                                                                                

test_example.py F                                                                                                                                         [100%]

=========================================================================== FAILURES ============================================================================
_________________________________________________________________________ test_example __________________________________________________________________________

monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f39de559220>

    def test_example(monkeypatch):
        # GIVEN environment variables are set for host and port
        monkeypatch.setenv('SERVICE_HOST', 'server.example.com')
        monkeypatch.setenv('SERVICE_PORT', '12345')
        #   AND a class instance is initialized without specifying a host or port
        example = Example()
        # THEN the instance should reflect the host and port specified in the environment variables
>       assert example.host == 'server.example.com'
E       AssertionError: assert 'localhost' == 'server.example.com'
E         - server.example.com
E         + localhost

test_example.py:12: AssertionError
==================================================================== short test summary info ====================================================================
FAILED test_example.py::test_example - AssertionError: assert 'localhost' == 'server.example.com'
======================================================================= 1 failed in 0.05s =======================================================================

您的測試失敗,因為您的代碼在導入模塊時加載了環境變量。 模塊級代碼很難測試,因為設置默認值的os.environ.get()調用在測試運行之前已經運行。 您必須從sys.modules模塊緩存中有效地刪除您的模塊,並且僅在 mocking 退出os.environ環境變量之后導入您的模塊,以測試導入時發生的情況。

您可以改為使用帶有default_factory參數的dataclass.field() 每當您創建數據類的實例時,它都會執行一個可調用以獲得默認值:

import os
from dataclasses import dataclass, field
from functools import partial


@dataclass
class Example:
    host: str = field(default_factory=partial(os.environ.get, 'SERVICE_HOST', 'localhost'))
    port: str = field(default_factory=partial(os.environ.get, 'SERVICE_PORT', '30650'))

我使用functools.partial() object創建了一個調用os.environ.get()的給定名稱和默認值。

請注意,我還將SERVICE_PORT的默認值更改為字符串; 畢竟, port字段被注釋為str ,而不是int :-)

如果您必須在導入時從環境變量中設置這些默認值,那么您可以讓pytestconftest.py模塊中模擬出這些環境變量; 這些是在導入測試之前導入的,因此您有機會在導入被測模塊之前進行調整。 但是,這不會讓您使用不同的默認值運行多個測試:

# add to conftest.py at the same package level, or higher.

@pytest.fixture(autouse=True, scope="session")
def mock_environment(monkeypatch):
    monkeypatch.setenv('SERVICE_HOST', 'server.example.com')
    monkeypatch.setenv('SERVICE_PORT', '12345')

上面的夾具示例,當放置在conftest.py中時,將在加載測試之前自動修補您的環境,因此在導入模塊之前,並且此補丁在測試 session 結束時自動撤消。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM