[英]How do I mock PyMongo for testing with a Flask app?
I've found similar questions, but they seem to only cover mocking MongoDB and don't mention Flask.我发现了类似的问题,但它们似乎只涵盖了模拟 MongoDB 而没有提到 Flask。
I have a Flask app and I'm trying to unit test it with PyTest (including PyTest-Mongo and PyTest-Flask).我有一个 Flask 应用程序,我正在尝试使用 PyTest(包括 PyTest-Mongo 和 PyTest-Flask)对其进行单元测试。 However, before I can even get to the point of writing any tests, my test script crashes.
然而,在我开始编写任何测试之前,我的测试脚本崩溃了。 The crash happens when importing the script with my Flash app: It's trying to create the PyMongo object without a url.
使用我的 Flash 应用程序导入脚本时发生崩溃:它试图创建没有 url 的 PyMongo 对象。
My question is: How can I ensure that PyMongo is mocked correctly at this point?我的问题是:如何确保此时正确模拟 PyMongo? According to the PyTest-Mongo documentation , the MongoDB test fixture should be passed to each of the test functions, but that doesn't help me if it's crashing on import.
根据PyTest-Mongo 文档,MongoDB 测试装置应该传递给每个测试函数,但是如果它在导入时崩溃,这对我没有帮助。
test_app.py: test_app.py:
import pytest
import pytest_mongodb
from app import app
@pytest.fixture
def client():
app.config['TESTING'] = True
return client
app.py:应用程序.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)
we can wrap app
and mongo
in a function This works because mongo
is used as a local variable.我们可以将
app
和mongo
包装在一个函数中这是有效的,因为mongo
被用作局部变量。
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
then we can create a test file and an application execution file with different databases:然后我们可以使用不同的数据库创建一个测试文件和一个应用程序执行文件:
test_app.py 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)
Sample of config.py file: 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
Needed a quick fix so I edited app.py
so that it only hard-fails if PyMongo doesn't initialise when the file is executed (ie it ignores PyMongo's failed initialisation when running unit-tests.)需要一个快速修复,所以我编辑了
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)
In my tests file, I just assign the mocked mongoDB client to the app in the tests that need it.在我的测试文件中,我只是将模拟的 mongoDB 客户端分配给需要它的测试中的应用程序。 Definitely not the ideal solution.
绝对不是理想的解决方案。
def test_redacted(client, mongodb):
app.mongodb = mongodb
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.