触发器测试必须隔离schema或用临时表,避免数据干扰;tSQLt.ExpectException捕获不可靠,应手动TRY...CATCH检查;需覆盖单/多/0行、事务边界及非幂等函数影响。

因为触发器不显式调用,也不返回值,靠人工观察或 SELECT 检查副作用极易漏掉逻辑错误、权限问题或事务边界异常。
触发器测试必须隔离 schema 或使用临时表
触发器绑定在真实表上,一旦多个测试共用同一张表,前一个测试留下的数据或触发状态可能干扰后一个测试。比如 INSERT 触发器修改了 audit_log 表,下一个测试若没清空它,就会误判“日志是否写入”。
- 推荐方案:每个测试用
CREATE TEMP TABLE搭建干净的临时表结构,再用CREATE TRIGGER绑定到它(PostgreSQL/SQL Server 均支持) - 不推荐方案:在测试中
DROP TRIGGER再重建——触发器无OR REPLACE语法,且依赖顺序可能被破坏,CI 环境容易失败 - 注意:SQL Server 中若用
tSQLt.FakeTable,它会自动重定向原表访问,但不会影响已存在的触发器,所以仍需先禁用或用tSQLt.ApplyTrigger显式控制
tSQLt.ExpectException 对触发器错误捕获不可靠
触发器里用 RAISERROR 或 THROW 抛错时,tSQLt.ExpectException 只能捕获顶层语句抛出的错误;如果触发器嵌套在另一个存储过程中执行,错误可能被外层 TRY...CATCH 吞掉,导致断言失效。
- 实操建议:直接在测试中用
INSERT/UPDATE/DELETE触发行为,配合TRY...CATCH+SELECT ERROR_MESSAGE()手动检查 - 避免把触发器逻辑塞进存储过程再测——这测的是包装层,不是触发器本身
- 若必须验证错误号,别只依赖
@ExpectedErrorNumber,要加SELECT XACT_STATE()确认事务是否已中断
边界条件测试必须覆盖隐式事务行为
触发器运行在父语句的事务上下文中,但多数人忽略它对 ROLLBACK 的响应方式。例如 INSTEAD OF 触发器里没写 ROLLBACK,而业务代码又没捕获错误,会导致部分数据写入成功、部分静默丢弃。
- 典型场景:测试
UPDATE触发器中对deleted表的引用——若原语句影响 0 行,deleted为空,触发器若未判空就SELECT TOP 1,会出错 - 必须测:单行、多行、0 行影响三种情况;还要在显式事务块里测
COMMIT和ROLLBACK后的状态一致性 - 容易被忽略的点:触发器里调用的函数若含
GETDATE()或NEWID(),会导致测试非幂等,应改用固定时间戳或SYSDATETIMEOFFSET()配合tSQLt.SpyProcedure拦截
触发器的隐蔽性决定了它不能靠“跑一次看看”来验证,真正难测的从来不是逻辑本身,而是它和事务、并发、权限三者的交叉影响——这些只有在受控的单元测试里才能稳定复现。

















