测试期间,MongoEngine连接到错误的数据库

时间:2019-06-03 15:37:04

标签: mongodb flask pytest mongoengine flask-mongoengine

上下文

我正在创建Flask通过MongoEngine扩展名使用flask-mongoengine连接到mongodb的应用。我按照configuration说明中的说明,使用application factory pattern创建了我的应用。

问题

运行测试时,我指定了名为datazilla_test的测试数据库,该数据库通过mongo传递到mongo.init_app(app)实例。即使我的app.config['MONGODB_DB']mongo.app.config['MONGODB_DB']实例具有正确的值(datazilla_test),该值也不会反映在mongo实例中。因此,当我运行断言assert mongo.get_db().name == mongo.app.config['MONGODB_DB']时,就会触发该错误AssertionError: assert 'datazzilla' == 'datazzilla_test'

问题

我在做什么错?为什么数据库连接持续使用默认数据库datazzilla而不是datazilla_test?如何解决?

源代码

# __init__.py
from flask_mongoengine import MongoEngine

mongo = MongoEngine()


def create_app(config=None):
    app = Flask(__name__)

    app.config['MONGODB_HOST'] = 'localhost'
    app.config['MONGODB_PORT'] = '27017'
    app.config['MONGODB_DB'] = 'datazzilla'

    # override default config
    if config is not None:
        app.config.from_mapping(config)

    mongo.init_app(app)

    return app
# conftest.py
import pytest
from app import mongo
from app import create_app


@pytest.fixture
def app():
    app = create_app({
        'MONGODB_DB': 'datazzilla_test',
    })

    assert mongo.get_db().name == mongo.app.config['MONGODB_DB']
    # AssertionError: assert 'datazzilla' == 'datazzilla_test'

    return app

2 个答案:

答案 0 :(得分:1)

调用夹具时,Mongoengine已经连接,当您从夹具调用app = create_app时,它将尝试重新建立连接,但会静默失败(因为它发现已建立了现有的默认连接)。

在mongoengine的开发版本中对此进行了重新设计(请参阅https://github.com/MongoEngine/mongoengine/pull/2038),但尚未发布(截至2019年6月4日)。该版本发布后,您可以通过调用disconnect_all

来断开任何现有的mongoengine连接。

在此期间,您可以: -检查在哪里创建现有连接并阻止它 -尝试使用以下方法断开现有连接:

from mongoengine.connection import disconnect, _connection_settings

@pytest.fixture
def app():
    disconnect()
    del _connection_settings['default']
    app = create_app(...)
    ...

但是它可能还有其他副作用

答案 1 :(得分:0)

上下文

巧合的是,我想出了解决此问题的方法。 @bagerard的答案是正确的!它适用于MongoClient,其中客户端连接设置为True-这是/应该是默认值。

MongoClient(host=['mongo:27017'], document_class=dict, tz_aware=False, connect=False, read_preference=Primary())

如果是这种情况,那么您必须按照{bagerard的解释,disconnect database and delete connection settings

解决方案

但是,如果将MongoClient的连接更改为False,则不必断开数据库连接并删除连接设置。最后对我有用的解决方案就是这种解决方案。

def create_app(config=None):
    ...
    app.config['MONGODB_CONNECT'] = False
    ...

注释

正如我先前所写。我偶然发现了该解决方案,我正在尝试解决此问题MongoClient opened before fork. Create MongoClient only after forking。原来,它可以解决两个问题:)

P.S如果有任何副作用,目前我还不知道它们!如果找到一些,请在评论部分中分享。