首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Flask-SqlAlchemy中模拟<ModelClass>.query.filter_by()

如何在Flask-SqlAlchemy中模拟<ModelClass>.query.filter_by()
EN

Stack Overflow用户
提问于 2017-02-27 17:26:31
回答 2查看 13.7K关注 0票数 19

简而言之

在Flask-SqlAlchemy中测试模型类时,我们如何模拟方法.query.filter_by()以便返回模拟的模型对象列表?

完整详细信息

假设我们有一个模型类,如下所示

代码语言:javascript
复制
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class SomeModel(db.Model):
    # more column mapping and methods go here

然后在我们的Flask代码中调用

代码语言:javascript
复制
SomeModel.query.filter_by(...)

在我们的测试代码中,使用带有mockingPython unittest模型,我们希望模拟filter_by()调用,以便它返回我们设计的测试用例下的模型对象列表。

我们怎样才能做到这一点?

附注:

我在谷歌上搜索只能找到this related post;尽管在课程开始时应用@patch("flask_sqlalchemy.SignallingSession", autospec=True)对我不起作用。

我还尝试像下面的代码片段那样模拟该函数

代码语言:javascript
复制
@patch('app.model.some_model.SomeModel.query.filter_by')
def test_some_case(self, filterbyMOCK):
    # more test logic goes here

并且代码在启动时立即出现错误

代码语言:javascript
复制
RuntimeError: application not registered on db instance and no application bound to current context

PyCharm集成开发环境中的完整错误如下所示。

代码语言:javascript
复制
Traceback (most recent call last):
  File "/home/namgivu/NN/code/someproject-cloud/venv/local/lib/python2.7/site-packages/mock/mock.py", line 1297, in patched
    arg = patching.__enter__()
  File "/home/namgivu/NN/code/someproject-cloud/venv/local/lib/python2.7/site-packages/mock/mock.py", line 1353, in __enter__
    self.target = self.getter()
  File "/home/namgivu/NN/code/someproject-cloud/venv/local/lib/python2.7/site-packages/mock/mock.py", line 1523, in <lambda>
    getter = lambda: _importer(target)
  File "/home/namgivu/NN/code/someproject-cloud/venv/local/lib/python2.7/site-packages/mock/mock.py", line 1210, in _importer
    thing = _dot_lookup(thing, comp, import_path)
  File "/home/namgivu/NN/code/someproject-cloud/venv/local/lib/python2.7/site-packages/mock/mock.py", line 1197, in _dot_lookup
    return getattr(thing, comp)
  File "/home/namgivu/NN/code/someproject-cloud/venv/local/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 428, in __get__
    return type.query_class(mapper, session=self.sa.session())
  File "/home/namgivu/NN/code/someproject-cloud/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 78, in __call__
    return self.registry()
  File "/home/namgivu/NN/code/someproject-cloud/venv/local/lib/python2.7/site-packages/sqlalchemy/util/_collections.py", line 990, in __call__
    return self.registry.setdefault(key, self.createfunc())
  File "/home/namgivu/NN/code/someproject-cloud/venv/local/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 136, in __init__
    self.app = db.get_app()
  File "/home/namgivu/NN/code/someproject-cloud/venv/local/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 809, in get_app
    raise RuntimeError('application not registered on db '
RuntimeError: application not registered on db instance and no application bound to current context
EN

Stack Overflow用户

回答已采纳

发布于 2017-02-27 17:34:43

您必须模拟整个映射器类;访问映射器上的query属性会导致会话加载:

代码语言:javascript
复制
@patch('app.model.some_model.SomeModel')
def test_some_case(self, some_model_mock):
    filter_by_mock = some_model_mock.query.filter_by
    # more test logic goes here

这是因为.query属性是一个描述符对象;访问它会触发到会话的绑定。

另一种方法是模拟_QueryProperty.__get__ method (它支持.query属性);只有在必须使用实际的SomeModel实例进行测试时才使用此方法:

代码语言:javascript
复制
@patch('flask_sqlalchemy._QueryProperty.__get__')
def test_some_case(self, query_property_getter_mock):
    filter_by_mock = query_property_getter_mock.return_value.filter_by
    # more test logic goes here

演示:

代码语言:javascript
复制
>>> from flask_sqlalchemy import SQLAlchemy
>>> db = SQLAlchemy()
>>> class SomeModel(db.Model):
...     id = db.Column(db.Integer, primary_key=True)
...
>>> from unittest import mock
>>> with mock.patch('__main__.SomeModel') as model_mock:
...     filter_by = model_mock.query.filter_by
...     SomeModel.query.filter_by(SomeModel.id == 'foo')
...
<MagicMock name='SomeModel.query.filter_by()' id='4438980312'>
>>> with mock.patch('flask_sqlalchemy._QueryProperty.__get__') as query_property_getter_mock:
...     filter_by_mock = query_property_getter_mock.return_value.filter_by
...     SomeModel.query.filter_by(SomeModel.id == 'foo')
...
<MagicMock name='__get__().filter_by()' id='4439035184'>
票数 17
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42482021

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档