How to mock <ModelClass>.query.filter_by() in Flask-SqlAlchemy How to mock <ModelClass>.query.filter_by() in Flask-SqlAlchemy flask flask

How to mock <ModelClass>.query.filter_by() in Flask-SqlAlchemy


You'll have to mock the whole mapper class; accessing the query attribute on the mapper causes a session load:

@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

That's because the .query attribute is a descriptor object; accessing it triggers the binding to a session.

The alternative would be to mock out the _QueryProperty.__get__ method (which backs the .query attribute); only use this if you must test with actual SomeModel instances:

@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

Demo:

>>> 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'>


Just a sum-up from Martijn Pieters answer

Target

  • We want to mock .query.filter_by().all() resulte.g. SomeModel.query.filter_by().all()

Code 01

@patch('flask_sqlalchemy._QueryProperty.__get__')def test (  self,  queryMOCK,):  #setup  queryMOCK\    .return_value.filter_by\    .return_value.all\    .return_value = [1,22]  #get actual  modelObj = SomeModel.query.filter_by().all()  print(modelObj)

Code 02 - similar as above and using with

def test(self):  with patch('flask_sqlalchemy._QueryProperty.__get__') as queryMOCK      #setup    queryMOCK\      .return_value.filter_by\      .return_value.all\      .return_value = [1,22]    #get actual    modelObj = SomeModel.query.filter_by().all()    print(modelObj)