SQLAlchemy1.4命令式映射下内存PostgreSQL测试未映射报错如何解决?
问题根因
你的报错核心是User类没有完成ORM映射,原因出在测试的session fixture逻辑:
- 你在fixture中调用
clear_mappers()会清空所有已注册的ORM映射关系,包括项目启动时myapp/orm.py执行map_imperatively注册的User映射 - 清空后仅调用
configure_mappers()只对声明式映射的类生效,你用的命令式映射不会自动重新注册,最终导致User类处于未映射状态,触发UnmappedInstanceError报错。
修改方案
1. 封装命令式映射注册逻辑(推荐,避免重复代码)
修改myapp/orm.py,把映射操作封装为可复用函数,同时去掉冗余的Metadata定义:
from sqlalchemy import Table, Column, Integer, String from sqlalchemy.orm import registry from myapp import model mapper_registry = registry() # 直接使用registry自带的metadata,不需要单独定义 metadata = mapper_registry.metadata user_table = Table( 'tb_user', metadata, Column('id', Integer, primary_key=True), Column('name', String(50)), Column('fullname', String(50)), Column('nickname', String(12)) ) def start_mappers(): """手动注册命令式映射,测试清空映射后可调用该函数重新注册""" mapper_registry.map_imperatively(model.User, user_table) # 模块加载时默认执行注册,不影响生产环境使用 start_mappers()
2. 修复测试session fixture逻辑
修改tests/test_postgresql_inmemory.py中的session fixture,清空映射后重新调用映射注册函数,删除无效的configure_mappers()调用:
@pytest.fixture def session(in_memory_db): clear_mappers() # 重新注册所有命令式映射 from myapp.orm import start_mappers start_mappers() Session = sessionmaker(bind=in_memory_db) session = Session() yield session clear_mappers()
3. 修复测试查询语法(可选,消除警告)
SQLAlchemy 1.4+要求原生SQL必须用text()包裹,否则会触发警告,修改测试用例:
def test_User_mapper_can_add(session): user = model.User(fullname="John Smith") session.add(user) session.commit() rows = list(session.execute(text("SELECT fullname FROM tb_user"))) assert rows == [("John Smith",)]
修改完成后重新运行测试即可正常通过。
内容的提问来源于stack exchange,提问作者Lionel Hamayon
相关产品推荐
相关产品推荐

