如何在更改env变量后正确导入fixture中的对象

问题描述 投票:0回答:1

我正在为Flask应用程序的配置文件编写测试。为了确保系统中设置的env变量不影响测试结果,我使用pytest的monkeypatch来创建可预测的测试结果。

我正在测试配置文件一次处于'干净'状态,其中一个夹具没有设置env变量,一次在'假'配置中,有一个夹具让我让monkeypatch在运行测试之前设置变量。

两个fixture都设置了env变量,然后在将配置对象传递给测试函数之前导入它。

当配置对象加载到文档的头部而不是夹具内部时,两个夹具都使用基于实际系统env变量的版本。

看起来第二个夹具不会导入配置对象,而是重用cleanConfig夹具创建的夹具。如何强制夹具重新导入配置对象?

test_config.朋友:

import pytest
from config import config

class TestConfigSettings(object):

@pytest.fixture(scope='function')
def cleanConfig(config_name, monkeypatch):
    def makeCleanConfig(config_name):

        monkeypatch.delenv('SECRET_KEY', raising=False)
        monkeypatch.delenv('DEV_DATABASE_URL', raising=False)

        from config import config
        configObject = config[config_name]

        return configObject
    return makeCleanConfig


@pytest.fixture(scope='function')
def fakeEnvConfig(config_name, monkeypatch):
    def makeFakeEnvConfig(config_name):

        monkeypatch.setenv('SECRET_KEY', 'fake difficult string')
        monkeypatch.setenv('DEV_DATABASE_URL', 'postgresql://fake:5432/fakeDevUrl')

        from config import config
        configObject = config[config_name]

        return configObject
    return makeFakeEnvConfig


def test_configObject_withDevelopmentConfig_containsCorrectSettings(self, cleanConfig):
    configObject = cleanConfig('development')

    assert configObject.SECRET_KEY == 'hard to guess string'
    assert configObject.DEBUG == True
    assert configObject.SQLALCHEMY_DATABASE_URI == None

def test_configObject_withDevelopmentConfigAndEnvSet_copiesEnvSettings(self, fakeEnvConfig):
    configObject = fakeEnvConfig('development')

    assert configObject.SECRET_KEY == 'fake difficult string'
    assert configObject.SQLALCHEMY_DATABASE_URI == 'postgresql://fake:5432/fakeDevUrl'

config.朋友:

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string'

class DevelopmentConfig(Config):
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL')

config = {
    'default': DevelopmentConfig,
    'development': DevelopmentConfig,
    ...
}
python flask pytest monkeypatching
1个回答
0
投票

我终于找到了解决问题的方法。通过使用reload()函数,您可以在更改内容(在这种情况下加载的env变量)后再次导入模块。为了能够使用它,我必须将导入更改为配置模块,而不是之前导入的配置字典,因为reload()对象仅适用于模块。新代码:

import pytest
from importlib import reload
import config

class TestConfigSettings(object):

@pytest.fixture(scope='function')
def cleanConfig(config_name, monkeypatch):
    def makeCleanConfig(config_name):

        monkeypatch.delenv('SECRET_KEY', raising=False)
        monkeypatch.delenv('DEV_DATABASE_URL', raising=False)

        reload(config)
        configObject = config.config[config_name]

        return configObject
    return makeCleanConfig

@pytest.fixture(scope='function')
def fakeEnvConfig(config_name, monkeypatch):
    def makeFakeEnvConfig(config_name):

        monkeypatch.setenv('SECRET_KEY', 'fake difficult string')
        monkeypatch.setenv('DEV_DATABASE_URL', 'postgresql://fake:5432/fakeDevUrl')

        reload(config)
        configObject = config.config[config_name]

        return configObject
    return makeFakeEnvConfig
© www.soinside.com 2019 - 2024. All rights reserved.