我最近在調用包含代碼中的一個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