在我的应用程序中,每个模型都有一个包含常用查询的类(我猜它有点像 DDD 语言中的“存储库”)。这些类中的每一个都被传递给 SQLAlchemy 会话对象,以在构造时创建查询。我很难确定在我的单元测试中运行某些查询的最佳方式。使用无处不在的博客示例,假设我有一个带有列和属性“日期”和“内容”的“发布”模型。我还有一个带有“find_latest”方法的“PostRepository”,它应该按“日期”降序查询所有帖子。它看起来像:
from myapp.models import Post
class PostRepository(object):
def __init__(self, session):
self._s = session
def find_latest(self):
return self._s.query(Post).order_by(Post.date.desc())
我在模拟 Post.date.desc() 调用时遇到了麻烦。现在我正在为我的单元测试中的 Post.date.desc 修补一个模拟,但我觉得可能有更好的方法。
编辑:我将 mox 用于模拟对象,我当前的单元测试看起来像:
import unittest
import mox
class TestPostRepository(unittest.TestCase):
def setUp(self):
self._mox = mox.Mox()
def _create_session_mock(self):
from sqlalchemy.orm.session import Session
return self._mox.CreateMock(Session)
def _create_query_mock(self):
from sqlalchemy.orm.query import Query
return self._mox.CreateMock(Query)
def _create_desc_mock(self):
from myapp.models import Post
return self._mox.CreateMock(Post.date.desc)
def test_find_latest(self):
from myapp.models.repositories import PostRepository
from myapp.models import Post
expected_result = 'test'
session_mock = self._create_session_mock()
query_mock = self._create_query_mock()
desc_mock = self._create_desc_mock()
# Monkey patch
tmp = Post.date.desc
Post.date.desc = desc_mock
session_mock.query(Post).AndReturn(query_mock)
query_mock.order_by(Post.date.desc().AndReturn('test')).AndReturn(query_mock)
query_mock.offset(0).AndReturn(query_mock)
query_mock.limit(10).AndReturn(expected_result)
self._mox.ReplayAll()
r = PostRepository(session_mock)
result = r.find_latest()
self._mox.VerifyAll()
self.assertEquals(expected_result, result)
Post.date.desc = tmp
这确实有效,虽然感觉很难看,我不确定为什么没有“Post.date.desc().AndReturn('test')”的“AndReturn('test')”片段会失败