模拟pytes的Sqlalchemy会话

2024-05-23 17:40:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我不知道这是否可以做到,但我想嘲笑我数据库会话保存. 在

我在用烧瓶和烧瓶炼金术。在

在数据库在

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

单元测试

^{pr2}$

方法是:

def post(cls):
    legends = schemas.Legends(many=True).load(request.get_json())

    for legend in legends:
        db.session.add(legend)

    db.session.commit()

    return {'message': 'legends saved'}, 200

我想嘲笑数据库会话添加以及数据库会话提交. 我试过db.session.savelegends.models.db.session.save和{}。它们都返回保存错误:

ModuleNotFoundError: No module named 'models.db.session'; 'models.db' is not a package

我不明白这个错误,也不知道如何解决它。在

或者我是在做一些完全错误的事情来嘲笑a数据库会话?在

谢谢。 德斯蒙德


Tags: fromimport数据库flaskdb烧瓶sqlalchemymodels
1条回答
网友
1楼 · 发布于 2024-05-23 17:40:24

你在这里遇到的问题最好是重组代码,使其更易于测试,而不是模仿每个组件并进行缓慢的集成测试。如果您养成了以这种方式编写测试的习惯,那么随着时间的推移,您将最终得到一个运行时间过长的缓慢构建,并且您将最终得到脆弱的测试(关于为什么快速测试很重要这一主题很好地谈了一下here)。

我们来看看这条路线:

def post(cls):
    legends = schemas.Legends(many=True).load(request.get_json())

    for legend in legends:
        db.session.add(legend)

    db.session.commit()

    return {'message': 'legends saved'}, 200

…然后分解它:

^{pr2}$

请注意,我们是如何将几乎所有的失败点从post隔离到LegendsPostService,而且,我们还从中移除了所有的flask内部(没有全局请求对象浮动,等等)。我们甚至给了它模仿session的能力,如果我们需要在以后进行测试的话。

我建议您集中精力为LegendsPostService编写测试用例。一旦您为LegendsPostService进行了出色的测试,那么就要确定您是否相信即使是更多的测试覆盖也会增加价值。如果您这样做了,然后考虑为post()编写一个简单的集成测试,将它们结合在一起。

接下来需要考虑的是如何在测试中考虑SQLAlchemy对象。我建议只使用FactoryBoy为您自动创建“模拟”模型。下面是一个完整的应用程序示例,说明如何用这种方式设置flask/sqlalchemy/factory boy:How do I produce nested JSON from database query with joins? Using Python / SQLAlchemy

下面是我如何为LegendsPostService编写一个测试(很抱歉,这有点草率,不能完美地代表您正在尝试的操作-但是您应该能够针对您的用例调整这些测试):


from factory.alchemy import SQLAlchemyModelFactory

class ModelFactory(SQLAlchemyModelFactory):
    class Meta:
        abstract = True
        sqlalchemy_session = db.session

# setup your factory for Legends:
class LegendsFactory(ModelFactory):
    logo_url = factory.Faker('image_url')
    class Meta:
        model = Legends


from unittest.mock import MagicMock, patch


# neither of these tests even need a database connection!
# so you should be able to write HUNDREDS of similar tests
# and you should be able to run hundreds of them in a matter seconds (not minutes)

def test_LegendsPostService_can_init():
    session = MagicMock()
    service = LegendsPostService(json_args={'foo': 'bar'}, _session=session)
    assert service.session is session
    assert service.json_args['foo'] == 'bar'


def test_LegendsPostService_can_post():
    session = MagicMock()
    service = LegendsPostService(json_args={'foo': 'bar'}, _session=session)

    # let's make some fake Legends for our service!
    legends = LegendsFactory.build_batch(2)

    with patch.object(service, '_get_legends') as _get_legends:
        _get_legends.return_value = legends
        legends_post_json = service.post()

    # look, Ma! No database connection!
    assert legends_post_json[0]['image_url'] == legends[0].image_url

我希望这有帮助!

相关问题 更多 >