首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在使用tSQLt进行测试时回滚事务

如何在使用tSQLt进行测试时回滚事务
EN

Stack Overflow用户
提问于 2012-01-23 22:26:53
回答 4查看 3.8K关注 0票数 7

我最近调用了一个在代码中包含rasierror的过程。raiserror位于try catch块中。在raiserror之后,BEGIN TRAN也在相同的try catch块中。Catch块用于在事务中发生错误时回滚事务。它这样做的方法是检查@@TRANCOUNT是否大于0,我知道它已经启动了一个事务,需要回滚。在使用tSQLt进行测试时,@@TRANCOUNT始终大于0,因此如果它命中CATCH块,则会执行ROLLBACK,并且tSQLt会失败(因为tSQLt正在事务中运行)。当我遇到错误并且CATCH块正在运行时,tSQLt总是无法通过测试。我没有办法测试raiserror的正确处理。如何创建可能回滚事务的测试用例?

EN

回答 4

Stack Overflow用户

发布于 2012-01-24 04:08:21

正如您所提到的,tSQLt在其自己的事务中运行每个测试。为了跟踪正在发生的事情,需要在测试结束时仍然打开相同的事务。SQL Server不支持嵌套事务,因此您的过程将回滚所有内容,包括框架为当前测试存储的状态信息。在这一点上,tSQLt只能假设发生了非常糟糕的事情。因此,它将测试标记为错误。

SQL Server本身不鼓励在过程内进行回滚,因为如果在打开的事务内调用该过程,则会引发错误。有关处理这种情况的方法和一些其他信息,请查看我关于how to rollback in procedures的博客文章。

票数 8
EN

Stack Overflow用户

发布于 2015-03-01 07:19:21

因为我正在阅读tSQLt,当我了解到每个测试都运行在一个事务中时,这是我想到的第一个问题之一。由于我的一些存储过程确实启动了事务,有些甚至使用嵌套事务,这可能会变得具有挑战性。我所学到的关于嵌套事务的知识,如果你应用以下规则,你可以保持你的代码干净的常量错误检查,并且仍然优雅地处理错误。

除非引发错误,否则在打开transactions

  • Always提交事务时,
  • 始终使用TRY/CATCH块
  • 始终在引发错误时回滚事务,除非@@TRANCOUNT =0
  • 始终重新清除错误,除非您绝对确定在存储过程开始时没有打开的事务。

记住这些规则,这里是一个proc实现和测试代码的示例。

代码语言:javascript
复制
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'
票数 3
EN

Stack Overflow用户

发布于 2014-03-19 21:22:53

最好在BEGIN TRANSACTION之后使用BEGIN TRY块。当我遇到类似的问题时,我这样做了。这更符合逻辑,因为在CATCH块中,我检查了IF @@TRANCOUNT > 0 ROLLBACK。如果在BEGIN TRANSACTION之前引发了另一个错误,则不需要检查此条件。在这种情况下,您可以测试您的RAISERROR功能。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8973138

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档