私のアプリケーションには、一般的に使用されるクエリを保持する各モデルのクラスがあります (DDD 言語の「リポジトリ」のようなものだと思います)。これらの各クラスには、構築時にクエリを作成するための SQLAlchemy セッション オブジェクトが渡されます。単体テストで特定のクエリが実行されていることをアサートする最良の方法を理解するのに少し苦労しています。どこにでもあるブログの例を使用して、列と属性「日付」と「コンテンツ」を持つ「投稿」モデルがあるとします。また、「date」の降順ですべての投稿を照会する「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')」部分がないと失敗する理由がわかりません