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

mock-Alchemy、pytest-sqlalchemy-mock を使わないでモックを作る - Oboe吹きプログラマの黙示録
の第2弾です。
mock-alchemy や、pytest-sqlalchemy-mock を使わない。
もう少し複雑なパターンです。
SQL直接実行で、パラメータを複数指定するパターンです。

まず、エンティティのクラスです。
entity.py

from sqlalchemy.orm import Session, registry
import sqlalchemy as db

mapper_reg = registry()
Base = mapper_reg.generate_base()
class Sample(Base):
    __tablename__ = 'samples'
    id  = db.Column(db.UUID, nullable=False, primary_key=True)
    name = db.Column(db.String(32), nullable=False)
    color = db.Column(db.String(32), nullable=False)
    point = db.Column(db.INT, nullable=False)
    create_time = db.Column(db.TIMESTAMP, nullable=False)

被テスト対象のSQLAlchemy実行しているものです。

from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker
engine = create_engine(f'postgresql://{username}:{password}@{host}:{port}/{database}')

sfactory = sessionmaker(autocommit=False, autoflush=True, bind=self.engine)
with sfactory() as session:
    sql = "SELECT * FROM samples WHERE color = :color AND point > :point"
    results = session.query(Sample)\
        .from_statement(text(sql))\
        .params(color=colorkey)\
        .params(point=pointvalue)\
        .all()

モックを作成

from typing import Optional, Dict, Any
from entity import Sample
class allFake:
    def all(self):
        return [Sample(id="001", name="test", color="Red", point=22,
                       create_time=datetime.datetime.strptime('2023-11-11 14:20:45', '%Y-%m-%d %H:%M:%S'))
                ]
class param2:
    def params(self, __params:Optional[Dict[str,Any]]=None, **key:Any):
        return allFake()
class param1:
    def params(self, __params:Optional[Dict[str,Any]]=None, **key:Any):
        return param2()
class from_statementFake():
    def from_statement(self, sql:str):
        return param1()
def queryFake(self):
    return from_statementFake()

mocker の patch 、side_effect で、この queryFake メソッドを指定します。

def test1(self, mocker):
       mocker.patch("sqlalchemy.orm.Session.query", side_effect=queryFake)

params の引数を SQLAlchemy どおりに再現するようにします。
return 文で連鎖するようにするのがポイントです。