我带有模型的 sqlalchemy 应用
## example file
## models.py -- path : app/models.py
db = SQLAlchemy(app)
class User(db.Model):
__tablename__ = 'User'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
class Book(db.Model):
__tablename__ = 'Book'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True, nullable=False)
owned_by = = db.Column(BigInt, db.ForeignKey('User.id'))
## i want to mock `user` and `book` returns by query
def check_user_own_book(user_id):
user = db.query.session(
User.id,
User.username,
).filter(
User.id == user_id
).one_or_none()
## more logic. abc
book = db.query.session(
Book.id,
Book.name,
).filter(
owned_by == user.id
).one_or_none()
## more logic
这是我的测试
from unittest import MagicMock, mock
def test_mock_session_query(fixture_user, fixture_book, session ):
# fixture_user , fixture_book are fixture object
# session is inited in confest.py
with mock.patch('flask_sqlalchemy._QueryProperty.__get__') as mock_model:
mock_model.filter.return_value.one_or_none.return_value = fixture_user
## let test
# query_user_with_session return None (which is true because there is no such user with id == 1000)
# -> Why do mock_model does not work and how to mock this `session.query` (1)
query_user_with_session = session.query(User.id, User.username).filter(User.id==1000).one_or_none()
# query_user_with_class returns fixture_user correctly with what we mocked
query_user_with_class = User.query.filter(User.id==1).one_or_none()
# query_book_with_class returns fixture_user (2)
query_user_with_session = Book.query.filter(Book.id=10000).one_or_none()
has_own_book = check_user_own_book(user_id=1) # this will fail because all query with one_or_none will return fixture_user
我为此研究了几天,但仍然没有任何答案:
Model.query
和 session.query(Model)
的行为不同。那么mock后面那个的技巧是什么
如何根据参数模拟 return_value
的 session.query(Model.column1, Model.columns2)
。例如:session.query(Model.column1, Model.columns2)
和 session.query(Model_2.column1, Model_2.columns2)
应该返回不同的
答案 0 :(得分:1)
不确定模拟 session.query()
是个好主意。它是为了什么?您可以立即模拟查询结果 (Result.one_or_none()
)。我也可以推荐使用 side_effect。这真的很容易、易懂且有用。下面是一个例子:
# somewhere in your code
def get_user_and_book():
user = db.session.query(...).filter(...).one_or_none()
book = db.session.query(...).filter(...).one_or_none()
return user, book
# test
class Example(unittest.TestCase):
def test_one_or_none(self):
with mock.patch('sqlalchemy.engine.result.Result.one_or_none', side_effect=(1, 2, 3, 4,)):
# get_user_and_book() calls one_or_none() 2 times
# so we'll expects 1, 2 - see side_effect
a, b = get_user_and_book()
self.assertEqual(1, a)
self.assertEqual(2, b)
# let's try one more time
c, d = get_user_and_book()
self.assertEqual(3, c)
self.assertEqual(4, d)
通过这种方式,您可以为所有可能的组合(用户找到 + 未找到书籍、用户找到 + 书籍找到等)编写测试