为notification_delay添加default参数为何影响CheckConstraint测试?
active = db.Column(db.Boolean, nullable=False, default=True) deleted = db.Column(db.Boolean, nullable=False, default=False) notification_delay = db.Column(db.Integer, nullable=False) ... __table_args__ = (db.CheckConstraint("NOT (deleted = 1 AND active = 1)", name="check_active_when_deleted"),)
### 测试用例 ```python def test_deleted_when_active(self, db): with pytest.raises(IntegrityError): a = Alarm( condition=TimeoutCondition( property_uuid='d891ef94-5775-440c-9ede-be423b3e70ae', timeout_sec=15 * 60 ), alarmtype=AlarmType.by_code('timeout'), deleted=True ) db.session.add(a) db.session.commit()
异常现象
该测试原本可正常触发IntegrityError,但为notification_delay字段添加default=0参数后,测试不再抛出该异常导致失败;移除异常捕获语句后,测试可正常通过。
原因解析
1. 初始测试的异常并非来自目标约束
在未给notification_delay添加default=0时,该字段无默认值且强制非空。创建Alarm实例时未传入该字段值,提交会话时会先触发非空约束的IntegrityError,此时数据库还未执行到check_active_when_deleted约束的检查。测试用例捕获到IntegrityError,误判为触发了删除与激活状态的冲突约束,但实际和目标约束无关。
2. 添加默认值后目标约束未生效
给notification_delay添加default=0后,非空约束不再触发,此时active使用默认值True、deleted被设为True,本该触发check_active_when_deleted约束,但测试未抛出异常,核心原因是该自定义约束未在数据库中实际生效,常见场景包括:
- 模型修改后未执行数据库迁移,数据库表中并未创建这个check约束;
- 使用的数据库(如SQLite)默认忽略check约束,需额外配置(如SQLAlchemy中设置
sqlite_enforce_check_constraints=True)才能启用; - ORM层面的默认值与数据库层面的默认值未同步,导致插入时数据库未识别到冲突状态。
内容的提问来源于stack exchange,提问作者Jan-Pieter
相关产品推荐
相关产品推荐

