【问题标题】:Access mongo instance in Flask Unit Tests在 Flask 单元测试中访问 mongo 实例
【发布时间】:2017-08-12 23:46:23
【问题描述】:

我在app/__init__.py 中有一个简单的 create_app 函数:

from flask import Flask
from flask_bootstrap import Bootstrap
from flask_login import LoginManager
from flask_pymongo import PyMongo
from .user_management import User

from config import app_config

login_manager = LoginManager()

mongo = PyMongo()

....

def create_app(config):
    app = Flask(__name__, instance_relative_config=True, static_folder='static')
    login_manager.init_app(app)
    login_manager.login_message = 'You must be logged in to view this page'
    login_manager.login_view = 'auth.login'

    Bootstrap(app)
    app.config.from_object(app_config[config])
    app.config.from_pyfile('config.py')

    if app.testing:
        mongo.init_app(app, config_prefix='MONGO2')
    else:
        mongo.init_app(app)

   ....

    return app

还有我的配置:

class Config():
    DEBUG = False
    MONGO_HOST = 'localhost'
    MONGO_PORT = 27017
    ....


class DevelopmentConfig(Config):
    DEBUG = True
    DEVELOPMENT = True


class TestingConfig(Config):
    TESTING = True
    DEBUG = False
    CSRF_ENABLED = False
    MONGO2_DBNAME = 'test'
....

app_config = {
    'testing': TestingConfig,
    'development': DevelopmentConfig,
    'production': ProductionConfig
}

在整个应用程序中,我从该文件导入 mongo 实例,并在整个应用程序中使用它。但是,我找不到设置一个新的 mongo 实例,该实例在不使用应用程序上下文的情况下使用“测试”数据库,就像我在这里所做的那样

我的单元测试文件如下所示。

from app import create_app
import unittest

from app import mongo

class TestCase(unittest.TestCase):
    def setUp(self):
        app = create_app('testing')
        self.app = app

    def tearDown(self):
        pass

    def test_mongo(self):
        with self.app.app_context():
            assert mongo.db.name == 'test'

if __name__ == '__main__':
    unittest.main()

这似乎根本不是要走的路。这也使得无法使用 app.test_client()。在烧瓶测试设置中实例化测试数据库的正确方法是什么?

【问题讨论】:

    标签: python unit-testing flask


    【解决方案1】:

    我不确定如何通过配置文件做到这一点,但我有另一种方法可能会让您感兴趣。

    当我为我的烧瓶/mongo 应用程序创建单元测试时,我只是简单地阅读了 sys.args(在我的“__init__.py”中)并从那里决定是否要使用测试数据库或实际数据库,如下所示:

    if "__init__.py" == sys.argv[0]:
        db = LoginManager()
    else:
        db = TestDB()  # if running unit tests
    

    我不知道这是处理单元测试的最稳健的方法,但它肯定是超级简单的方法,并且可以完成工作。

    如果您对整个设置感兴趣,请查看我的example app

    【讨论】:

      【解决方案2】:

      您需要在每个需要访问配置中定义的不同数据库的不同单元测试中重新创建 mongo 对象。我是这样做的,为了进行真正的测试,我向数据库写入了一个值,并确保我可以用两种不同的方式读回它:

      import uuid
      from datetime import datetime
      from flask_testing import TestCase
      from flask_pymongo import PyMongo
      from project import app
      
      class TestMongoDev(TestCase):
          def create_app(self):
              app.config.from_object('project.config.DevelopmentConfig')
              return app
      
          def test_mongo_development(self):
              mongo = PyMongo(app)
              testval = str(uuid.uuid4())
              inserted_id = mongo.db.test.insert_one({
                  'testedAt': datetime.now(),
                  'testval': testval
              }).inserted_id
              self.assertTrue(mongo.db.name == 'dev')
              self.assertTrue(mongo.db.test.find_one({'testval': testval})['testval'] == testval)
              self.assertTrue(mongo.db.test.find_one({'_id': inserted_id})['testval'] == testval)
      
      
      class TestMongoTest(TestCase):
          def create_app(self):
              app.config.from_object('project.config.TestingConfig')
              return app
      
          def test_mongo_testing(self):
              mongo = PyMongo(app)
              testval = str(uuid.uuid4())
              inserted_id = mongo.db.test.insert_one({
                  'testedAt': datetime.now(),
                  'testval': testval
              }).inserted_id
              self.assertTrue(mongo.db.name == 'test')
              self.assertTrue(mongo.db.test.find_one({'testval': testval})['testval'] == testval)
              self.assertTrue(mongo.db.test.find_one({'_id': inserted_id})['testval'] == testval)
      
      
      class TestMongoProd(TestCase):
          def create_app(self):
              app.config.from_object('project.config.ProductionConfig')
              return app
      
          def test_mongo_production(self):
              mongo = PyMongo(app)
              testval = str(uuid.uuid4())
              inserted_id = mongo.db.test.insert_one({
                  'testedAt': datetime.now(),
                  'testval': testval
              }).inserted_id
              self.assertTrue(mongo.db.name == 'prod')
              self.assertTrue(mongo.db.test.find_one({'testval': testval})['testval'] == testval)
              self.assertTrue(mongo.db.test.find_one({'_id': inserted_id})['testval'] == testval)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-12-17
        • 1970-01-01
        • 2014-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多