如何模拟PyMongo以使用Flask应用进行测试?

时间:2019-05-07 19:12:52

标签: python mongodb flask pytest

我发现了类似的问题,但它们似乎只涵盖了模拟MongoDB,没有提及Flask。

我有一个Flask应用程序,我正在尝试使用PyTest(包括PyTest-Mongo和PyTest-Flask)对其进行单元测试。但是,在我什至无法编写任何测试之前,我的测试脚本就会崩溃。使用Flash应用程序导入脚本时会发生崩溃:它正在尝试创建没有url的PyMongo对象。

我的问题是:在这一点上如何确保正确模拟PyMongo?根据{{​​3}}的说法,应该将MongoDB测试装置传递给每个测试函数,但是如果它在导入时崩溃,那对我没有帮助。

test_app.py:

import pytest
import pytest_mongodb

from app import app


@pytest.fixture
def client():
    app.config['TESTING'] = True
    return client

app.py:

import ...

app = Flask(__name__)
app.config["MONGO_DBNAME"] = os.environ.get('DB_NAME')
app.config["MONGO_URI"] = os.environ.get('MONGO_URI')
app.secret_key = os.environ.get('SECRET')

mongo = PyMongo(app)

...

if __name__ == '__main__':
app.run(host=os.environ.get('IP'),
        port=int(os.environ.get('PORT')),
        debug=False)

2 个答案:

答案 0 :(得分:1)

我们可以将appmongo包装在一个函数中 之所以有效,是因为mongo被用作 local 变量。

app.py

from flask import Flask
from flask_pymongo import PyMongo

def get_app_with_config(config):

    app = Flask(__name__)
    app.config.from_object(config)
    mongo = PyMongo(app)

    @app.route("/")
    def index():
        pass
    .
    .
    
    return app, mongo

然后我们可以使用不同的数据库创建一个测试文件和一个应用程序执行文件:

test_app.py

from app import get_app_with_config
from config import TestConfig

app, mongo = get_app_with_config(TestConfig)

run.py

from app import get_app_with_config
from config import RunConfig

app, mongo = get_app_with_config(RunConfig)

if __name__ == '__main__':
    app.run(port=8000)

config.py 文件的示例:

class RunConfig:

    MONGO_HOST = '192.168.1.37'
    MONGO_PORT = 27017
    MONGO_DBNAME = 'my_database'
    MONGO_URI = f"mongodb://{MONGO_HOST}:{MONGO_PORT}/{MONGO_DBNAME}"

class TestConfig:

    MONGO_HOST = '192.168.1.37'
    MONGO_PORT = 27017
    MONGO_DBNAME = 'my_database_test'
    MONGO_URI = f"mongodb://{MONGO_HOST}:{MONGO_PORT}/{MONGO_DBNAME}"
    TESTING = True

答案 1 :(得分:0)

需要快速修复,因此我编辑了app.py,使其仅在执行文件时PyMongo不初始化时才失败(即,在运行单元测试时它忽略了PyMongo的失败初始化)。

app = Flask(__name__)
app.config["MONGO_DBNAME"] = os.environ.get('DB_NAME')
app.config["MONGO_URI"] = os.environ.get('MONGO_URI')
app.secret_key = os.environ.get('SECRET')

try:
    mongodb = PyMongo(app).db
except ValueError:
    """We don't provide a URI when running unit tests, so PyMongo will fail to initialize.
    This is okay because we replace it with a version for testing anyway. """
    print('PyMongo not initialized!')
    mongodb = None
.
.
.

if __name__ == '__main__':
    if not mongodb:
        print('Cannot run. PyMongo failed to initialize. Double check environment variables.')
        exit(1)

    app.run(host=os.environ.get('IP'),
            port=int(os.environ.get('PORT')),
            debug=False)

在我的测试文件中,我只是将模拟的mongoDB客户端分配给需要它的测试中的应用程序。绝对不是理想的解决方案。

def test_redacted(client, mongodb):
    app.mongodb = mongodb
    ...