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 文で連鎖するようにするのがポイントです。