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

使用pytest和mongoengine测试时数据写入主库而非测试库如何解决

问题:pytest运行时数据写入主数据库而非测试库

我已安装以下包:

python -m pip install pytest pytest-django

并创建了一个fixture:

# core/services/tests/fixtures/checkout.py

import pytest

from bson import ObjectId
from datetime import datetime

from core.models.src.checkout import Checkout


@pytest.fixture(scope="session")
def checkout(mongo_db):
    checkout = Checkout(
        user_id=59,
        amount=35_641,
    )
    checkout.save()
    return checkout

将其导入到同目录的conftest.py中:

# core/service/tests/conftest.py

from core.service.tests.fixtures.checkout import *

以下是我连接测试数据库的方式:

# conftest.py

import pytest

from mongoengine import connect, disconnect, connection

@pytest.fixture(scope="session", autouse=True)
def mongo_db():
    connect(
        db="db",
        name="testdb",
        alias="test_db",
        host="mongodb://localhost:27017/",
        serverSelectionTimeoutMS=5000,
    )

    connection._connections.clear()

    yield

    disconnect()

这是我的测试代码:

import json
import pytest

from core.service.checkout import a_function


def test_a_function(checkout):
    assert checkout.value is False
    response = a_function(id=checkout.id, value=True)
    assert response.status_code == 200
    response_data = json.loads(response.content.decode("UTF-8"))
    assert response_data.get("success", None) is True
    checkout.reload()
    assert checkout.value is True

但每次运行pytest时,都会在主数据库中创建新记录。请问如何修改才能使用测试数据库?


问题根源及修复方案

1. 删除错误的连接清空代码

你的mongo_db fixture里调用了connection._connections.clear(),这会直接清空刚建立的测试数据库连接,导致后续操作默认使用主库连接。必须删除这行代码。

2. 给模型指定测试数据库别名

Checkout模型需要明确绑定测试库的别名,否则会默认使用主库。修改模型文件(core/models/src/checkout.py):

from mongoengine import Document, fields

class Checkout(Document):
    user_id = fields.IntField()
    amount = fields.IntField()
    value = fields.BooleanField(default=False)
    
    # 添加这行,绑定测试库别名
    meta = {
        'db_alias': 'test_db'
    }

如果模型已有meta配置,直接追加'db_alias': 'test_db'即可。

3. 修正数据库连接参数

connect函数中的db和name参数重复,调整参数明确指定测试库名称:

@pytest.fixture(scope="session", autouse=True)
def mongo_db():
    # 直接指定测试库名称为testdb,绑定别名test_db
    conn = connect(
        db="testdb",
        alias="test_db",
        host="mongodb://localhost:27017/",
        serverSelectionTimeoutMS=5000,
    )

    yield conn

    # 断开时明确指定测试库别名
    disconnect(alias="test_db")

4. 确保fixture操作使用测试库

在checkout fixture中,显式指定保存到测试库(如果模型已配置db_alias,此步骤可省略,显式指定更保险):

@pytest.fixture(scope="session")
def checkout(mongo_db):
    checkout = Checkout(
        user_id=59,
        amount=35_641,
    )
    checkout.save(alias="test_db")
    return checkout

5. 检查业务函数的数据库操作

确保a_function内部操作Checkout时指定测试库别名,比如:

# core/service/checkout.py中的a_function示例
def a_function(id, value):
    # 查询时指定别名
    checkout = Checkout.objects(alias="test_db").get(id=id)
    checkout.value = value
    checkout.save(alias="test_db")
    # 其他业务逻辑...

完成以上修改后,运行pytest时数据就会写入testdb测试数据库,而非主库。


内容的提问来源于stack exchange,提问作者Amir Shabani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 09:06:18