You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pytest中Mock Python函数的MongoDB URI配置调用?

问题场景

我正在为get_indexes函数编写Pytest测试,该函数通过import_configuration("mongodb", "uri")获取MongoDB URI并创建MongoClient连接db_data库。我已经用mongomock编写了数据库fixture,但不知道如何Mock函数中创建MongoClient的逻辑,让函数直接使用fixture中的db_data实例,而非读取配置文件的URI。

目标函数代码

def get_indexes(collection, database, criterias):
    file = database.files.find_one(
        {"_id": bson.ObjectId(collection)}, {"_id": 0, "internal_name": 1})["internal_name"]
    server = MongoClient(import_configuration("mongodb", "uri"))
    database_data = server["db_data"]
    indexes = database_data[file].index_information()

    fields_names = []
    for criteria in criterias:
        field = database.champs.find_one(
            {"_id": criteria["field"]}, {"_id": 0, "internal_name": 1})["internal_name"]
        fields_names.append(field)

    names_joined = ""
    for field in fields_names:
        names_joined +=  f"{field}_1"

    if names_joined in indexes:
        return True

    return False

现有测试fixture代码

@pytest.fixture(scope='session')
def database():
    client = mongomock.MongoClient("mongodb://127.0.0.1:27016/")
    db = client.db
    db_data = client.db_data

    # Files
    objects = [
        {
            "_id": ObjectId("65afa95dbd2214f7afa80aa6"),
            "internal_name": "test",
            "name": "toto",
            "percent_s": 80,
            "percent_m": 50
        },
        {
            "_id": ObjectId("65afa95dbd2214f7afa80aa7"),
            "internal_name": "test2",
            "name": "titi",
            "percent_s": 45,
            "percent_m": 12
        },
    ]
    db.files.insert_many(objects)  # 修正原fixture拼写错误:匹配函数中的database.files

    # Champs
    objects = [
        {
            "_id": ObjectId("65afa95dbd2214f7afa80aa8"),
            "internal_name": "name"
        },
        {
            "_id": ObjectId("65afa95dbd2214f7afa80aa9"),
            "internal_name": "test2"
        },
    ]
    db.champs.insert_many(objects)  # 修正原fixture拼写错误:匹配函数中的database.champs

    # db_data初始化
    file = db.files.find_one({"_id": ObjectId("65afa95dbd2214f7afa80aa6")}, {"_id": 0, "internal_name": 1})["internal_name"]
    objects = [
        {
            "_id": "idindividu01",
            "_idhouse": "idfoyer01",
            "index": "index"
        },
        {
            "_id": "idindividu02",
            "_idhouse": "idfoyer02",
            "index": "index"
        }
    ]
    db_data[file].insert_many(objects)
    collection = db_data[file]
    collection.create_index([("index", ASCENDING)], background=False)

    return db, db_data

解决方案

通过Mock函数中的MongoClient类,让它返回fixture中已初始化的mongomock客户端,跳过读取配置文件创建新连接的逻辑,直接复用fixture中的db_data实例。

修改后的测试函数

from pytest_mock import MockerFixture
from bson import ObjectId

@pytest.mark.parametrize(
        "collection,criterias,expected",
    [
        # 修正测试用例键名:匹配函数中的criteria["field"]
        (ObjectId("65afa95dbd2214f7afa80aa6"), [{"field": ObjectId("65afa95dbd2214f7afa80aa8")}, {"field": ObjectId("65afa95dbd2214f7afa80aa9")}], False),
    ],
)
def test_get_indexes(collection, criterias, expected, database, mocker: MockerFixture):
    # 从fixture中获取db_data实例及对应客户端
    _, db_data = database
    # 替换"your_module"为get_indexes函数所在的模块名(例如src.data_utils)
    mock_mongo_client = mocker.patch("your_module.MongoClient")
    # 让Mock的MongoClient返回fixture中的mongomock客户端
    mock_mongo_client.return_value = db_data.client

    # 执行测试并断言结果
    value = get_indexes(collection, database[0], criterias)
    assert value == expected

关键说明

  1. Mock路径正确性:必须使用get_indexes函数所在模块中导入的MongoClient路径,而非直接pymongo.MongoClient,因为Python Mock基于模块命名空间生效。
  2. 修正代码不一致:原fixture和测试用例中存在拼写/键名错误,需统一匹配函数中的字段名才能保证测试正常运行。
  3. 复用fixture资源:通过db_data.client直接获取fixture中创建的客户端实例,确保函数使用的数据库与测试初始化的完全一致。

内容的提问来源于stack exchange,提问作者Morgane FLAMANT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:37:02