tSQLt中TRY/CATCH块报错后AssertEqualsTableSchema等断言失效问题
tSQLt TRY/CATCH块后复杂断言报错问题解决方案
根本原因
这个现象是SQL Server的事务机制与tSQLt不同断言的内部实现差异共同导致的,不属于不可解决的底层限制:
- 当TRY块内触发严重级别的错误时,SQL Server会将当前事务标记为不可提交状态(即
XACT_STATE()返回-1),此时事务仅支持全量回滚,禁止任何写入日志、创建/修改对象类的操作,否则会直接抛出你遇到的事务不可提交错误。 - 你列出的
AssertEquals这类简单断言,内部仅做参数值的逻辑比较,不涉及任何写操作,所以在不可提交事务中也可以正常运行。 - 而
AssertEqualsTableSchema、AssertEqualsTable这类复杂断言,内部需要创建临时表、写入tSQLt内部统计日志等写操作,碰到不可提交的事务自然会报错。
解决方案
方案1(推荐,符合tSQLt设计规范)
如果你的测试目的就是验证指定逻辑会抛出异常,不要手动写TRY/CATCH块,直接使用tSQLt内置的tSQLt.ExpectException方法,不会触发事务不可提交的问题,示例用法:
EXEC tSQLt.ExpectException @ExpectedMessage = '转换失败' -- 执行你预期会抛错的逻辑 DECLARE @IntegerVariable AS INT; SET @IntegerVariable = 'a string';
方案2(兼容自定义TRY/CATCH场景)
如果确实需要手动实现TRY/CATCH逻辑,在CATCH块结束后、调用复杂断言之前,先重置事务状态即可:
BEGIN CATCH PRINT('An error happened.'); END CATCH -- 新增以下代码重置事务状态 IF XACT_STATE() = -1 BEGIN ROLLBACK TRANSACTION; BEGIN TRANSACTION; END
这段代码会将不可提交的事务全量回滚,再新开一个可正常执行写操作的事务,后续所有复杂断言都可以正常运行。
验证效果
把上述重置事务的代码加入你给出的复现代码中,再运行AssertEqualsTableSchema断言,测试会正常返回通过/失败结果,不会再触发事务报错。
内容的提问来源于stack exchange,提问作者pygri
相关产品推荐
相关产品推荐

