mock-Alchemy、pytest-sqlalchemy-mock を使わないでモックを作る

pytest-mock だけで頑張る方法

今回目的の対象の検索クエリ

'name'列を指定してSQLの結果から1行目の結果の 'color'列の値を取得するクエリ
のメソッドがある。

class Sample:
    def queryColor(self, name:str)->str:
        sfactory = sessionmaker(autocommit=False, autoflush=True, bind=engine)
        with sfactory() as session:
            sql = "SELECT * FROM view_data WHERE name = '%s' ORDER BY point ASC"
            dictrows = session.execute(text(sql % color)).mappings().all()
            print(dictrows)
            return "color is " + dictrows[0].get('color')

この Session の execute の結果、1行目取得をモックでテスト期待値に置き換える

sqlalchemy.engine.cursor.CursorResult が、class CursorResult(Result[_T]):
であることから、sqlalchemy.engine.result.Result
def mappings(self) -> MappingResult:
class MappingResult(_WithKeys, FilterResult[RowMapping]): から、
def all(self) -> Sequence[RowMapping]:
で、dict の list なのである。

そこで、、pytetst のソースで以下のように、
  execute メソッドの Fake
  mappings() の Fake
  all() の Fake
を用意する。

class AllFake():
    def all(self):
        return [{'id': 'a001', 'name': 'Tokyo', 'color': 'Red', 'point': 14}]
class MappingFake():
    def mappings(self):
        return AllFake()
def executeFake(self):
    return MappingFake()

そして、sqlalchemy.orm.Session.execute に対して実行するメソッド executeFake を指定する。

class TestSample:
    def test_1(self, mocker):
        m = mocker.patch("sqlalchemy.orm.Session.execute" , side_effect=executeFake)
        s = Sample()
        color = s.queryColor('Tokyo')
        assert color == "color is Red"