在Python中模拟类,在命名空间包中有效,但不适用于常规包

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

背景

我正在为我的应用程序编写单元测试。

我在

configuration/connections.py
中有一个带有配置的模块(通常由环境变量定义):

from typing import Literal

from pydantic_settings import BaseSettings

class StorageConfig(BaseSettings):
    storage_name: Literal["file", "s3"]

此配置在模块中调用

connections/storage/main.py
:

import fsspec

from configuration.connections import StorageConfig

storage_config = StorageConfig()

fs: fsspec.AbstractFileSystem = fsspec.filesystem(storage_config.storage_name)

并且因为当我运行单元测试时环境配置不存在,所以我尝试模拟该对象

StorageConfig

import pytest
from pydantic import BaseModel

@pytest.fixture(autouse=True)
def local_config(mocker):
    class LocalStorageConfig(BaseModel):
        storage_name: str = "file"

    mocker.patch("configuration.connections.StorageConfig", new=LocalStorageConfig)

问题

根据我的文件夹架构,模拟可以工作,有时则不能。

  1. 如果我有

    connections.storage
    作为命名空间包,并且我的测试在
    connections/storage/tests/test_storage.py
    中并且我直接修补
    configuration.connections.StorageConfig
    (而不是文档希望我做的事情),那么它工作得很好.

  2. 如果

    connections.storage
    常规包,并且所有其他内容如1.中所示,则不再起作用

  3. 如果我将测试移至

    tests/integration/test_storage.py
    并保留 2. 中的所有其他内容,则它可以工作。

问题

  1. 为什么常规包和命名空间包对mock有影响?
  2. 为什么我的测试文件的位置会影响模拟?
  3. 为什么当我按照文档提示修补
    connections.storage.main.StorageConfig
    时它无法工作?

感谢您花时间帮助我理解这个问题:)

python unit-testing mocking pytest
1个回答
0
投票

main.py
使用名称
StorageConfig
(或
main.StorageConfig
),而不是
configurations.connections.StorageConfig
。这就是您需要修补的名称。

import pytest
from pydantic import BaseModel

@pytest.fixture(autouse=True)
def local_config(mocker):
    class LocalStorageConfig(BaseModel):
        storage_name: str = "file"

    mocker.patch("main.StorageConfig", new=LocalStorageConfig)
© www.soinside.com 2019 - 2024. All rights reserved.