我最近在调用包含代码中的一个rasierror的过程。 raiserror在try catch块中。另外一个BEGIN TRAN在raiserror之后也在同一个try catch块中。 Catch块设计用于在事务发生错误时对事务进行ROLLBACK。这样做的方式是检查@@ TRANCOUNT是否大于0我知道它已经启动了一个事务并需要ROLLBACK。使用tSQLt进行测试时,@@ TRANCOUNT始终> 0,因此如果它遇到CATCH块,则会执行ROLLBACK并且tSQLt失败(因为tSQLt正在事务中运行)。当我发现一个错误并且运行CATCH块时,tSQLt总是不能通过测试。我无法测试正确处理raiserror的情况。你将如何创建一个可能会ROLLBACK事务的测试用例?如何在使用tSQLt进行测试时回滚事务
回答
正如您所提到的,tSQLt在自己的事务中运行每个测试。跟踪发生的事情依赖于同一事务在测试完成时仍然处于打开状态。 SQL Server不支持嵌套事务,因此您的过程将回滚所有内容,包括框架为当前测试存储的状态信息。那时tSQLt只能认为发生了一些非常糟糕的事情。因此它将测试标记为错误。
如果在打开的事务中调用该过程,SQL Server本身会阻止在过程内部进行回滚。有关如何处理这种情况和一些额外的信息请查看我的博客文章how to rollback in procedures。
最好在BEGIN TRANSACTION
之后使用BEGIN TRY
块。当我遇到类似问题时,我做了这个。这更合乎逻辑,因为在CATCH
区块我检查了IF @@TRANCOUNT > 0 ROLLBACK
。如果在BEGIN TRANSACTION
之前发生另一个错误,则无需检查此情况。在这种情况下,您可以测试您的RAISERROR
功能。
+1以上两个答案。
但是,如果您不想使用TRY .. CATCH,请尝试以下代码。行-----
之间的部分代表测试,并且在代表tSQLt的之前和之后调用您的测试。正如你所看到的,在调用测试之前,由tSQLt开始的事务仍然在,正如它所期望的那样,是否发生错误。 @@ TRANSCOUNT仍然是1
您可以将RAISERROR注释掉,并在不引发异常的情况下尝试使用它。
SET NOCOUNT ON
BEGIN TRANSACTION -- DONE BY tSQLt
PRINT 'Inside tSQLt before calling the test: @@TRANCOUNT = ' + CONVERT (VARCHAR, @@TRANCOUNT)
---------------------------------
PRINT ' Start of test ---------------------------'
SAVE TRANSACTION Savepoint
PRINT ' Inside the test: @@TRANCOUNT = ' + CONVERT (VARCHAR, @@TRANCOUNT)
BEGIN TRANSACTION -- PART OF THE TEST
PRINT ' Transaction in the test: @@TRANCOUNT = ' + CONVERT (VARCHAR, @@TRANCOUNT)
RAISERROR ('A very nice error', 16, 0)
PRINT ' @@ERROR = ' + CONVERT(VARCHAR,@@ERROR)
-- PART OF THE TEST - CLEAN-UP
IF @@ERROR <> 0 ROLLBACK TRANSACTION Savepoint -- Not all the way, just tothe save point
ELSE COMMIT TRANSACTION
PRINT ' About to finish the test: @@TRANCOUNT = ' + CONVERT (VARCHAR, @@TRANCOUNT)
PRINT ' End of test ---------------------------'
---------------------------------
ROLLBACK TRANSACTION -- DONE BY tSQLt
PRINT 'Inside tSQLt after finishing the test: @@TRANCOUNT = ' + CONVERT (VARCHAR, @@TRANCOUNT)
正如我只是读了上tSQLt这是的浮现在脑海的第一个问题时,我已经学会在交易的每个测试运行。由于我的一些存储过程确实启动了事务处理,有些甚至使用嵌套事务处理,这可能会变得很有挑战性我已经了解到嵌套事务,如果你应用以下规则,你可以保持你的代码清理常量错误检查,并且仍然适度地处理错误。
- 打开交易时,始终使用try/catch块
- 始终提交事务,除非误差升至
- 始终回滚事务时被升高除非@@ TRANCOUNT = 0
- 错误除非您确定在存储过程开始时没有打开任何事务,否则请始终重新评估错误。
保持这些规则在这里是一个proc实现和测试代码的例子来测试它。
ALTER PROC testProc
@IshouldFail BIT
AS
BEGIN TRY
BEGIN TRAN
IF @IshouldFail = 1
RAISERROR('failure', 16, 1);
COMMIT
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK;
-- Do some exception handling
-- You'll need to reraise the error to prevent exceptions about inconsistent
-- @@TRANCOUNT before/after execution of the stored proc.
RAISERROR('failure', 16, 1);
END CATCH
GO
--EXEC tSQLt.NewTestClass 'tSQLt.experiments';
--GO
ALTER PROCEDURE [tSQLt.experiments].[test testProc nested transaction fails]
AS
BEGIN
--Assemble
DECLARE @CatchWasHit CHAR(1) = 'N';
--Act
BEGIN TRY
EXEC dbo.testProc 1
END TRY
BEGIN CATCH
IF @@TRANCOUNT = 0
BEGIN TRAN --reopen an transaction
SET @CatchWasHit = 'Y';
END CATCH
--Assert
EXEC tSQLt.AssertEqualsString @Expected = N'Y', @Actual = @CatchWasHit, @Message = N'Exception was expected'
END;
GO
ALTER PROCEDURE [tSQLt.experiments].[test testProc nested transaction succeeds]
AS
BEGIN
--Act
EXEC dbo.testProc 0
END;
GO
EXEC tSQLt.Run @TestName = N'tSQLt.experiments'
- 1. 使用事务回滚进行测试
- 2. 如何在symfony2中使用phpUnit进行测试时回滚任何事务
- 3. 如何在使用Symfony2进行功能测试时回滚事务
- 4. 如何在JUnit中使用Spring测试服务时回滚数据库事务?
- 5. 在计算列上使用tSQLt进行单元测试
- 6. Junit测试在事务后不回滚
- 7. 在cucumber-jvm测试中回滚事务
- 8. 使用DatabaseCleaner和事务进行快速测试。如何调试?
- 9. Spring @transactional在使用JUnit4进行测试时未启动事务
- 10. 使用PostgreSQL在SQLAlchemy测试中回滚数据库事务
- 11. JUnit测试总是回滚事务
- 12. Spring集成测试事务不回滚
- 13. 春季测试事务回滚问题
- 14. Spring JDBC测试上的事务回滚
- 15. Hibernate:如何在JUnit测试之后回滚事务?
- 16. 在单元测试存储过程时回滚嵌套事务
- 17. 在春季测试中未回滚事务以进行删除操作
- 18. 使用apache骆驼测试回滚事务
- 19. 如何在ssis中进行事务回滚?
- 20. 如何使用PyQT4回滚事务
- 21. 事务自动进行回滚
- 22. 如何整合回滚嵌套事务与Propagation.REQUIRES_NEW测试
- 23. 如何在事务内使用INNODB和MyISAM表进行高效回滚?
- 24. 如何在使用Apache Camel事务时回滚文件写入?
- 25. CMT回滚:如何回滚事务
- 26. 春季测试:执行测试方法后未回滚的事务
- 27. 使用事务日志回滚事务
- 28. 针对tSQLt的SQLCop测试
- 29. tSQLt,触发器和测试
- 30. tSQLt的SQLCop测试 - 新增
的可能重复[需要回滚如果查询完成有错误?(http://stackoverflow.com/questions/8991207/is-rollback-needed-if-query-completed-with-errors) – Dijkgraaf