4

使用 tSQLt 1.0.5873.27393,我正在尝试为存储过程编写 tSQLt 测试,该存储过程将捕获在CATCH块中的错误记录到日志表中,然后再将错误重新抛出到调用会话。

我可以使用 成功测试错误消息是否被重新抛出tSQLt.ExpectException,但副作用似乎是在调用后无法测试任何其他断言tSQLt.ExpectException- 所以我无法测试错误是否已写入日志表。

我能想出的最简单的测试可以证明问题是:

CREATE PROC MyTests.[test ExpectException]
AS
BEGIN
    EXEC tSQLt.ExpectException;
    THROW 50001, 'Error message',1

    EXEC tSQLt.AssertEquals 0,1, '0=1'
END
GO

执行时会产生以下(意外)输出:

|No|Test Case Name                  |Dur(ms)|Result |
+--+--------------------------------+-------+-------+
|1 |[MyTests].[test ExpectException]|      3|Success|

使用分析器跟踪,我可以看到断言AssertEquals从未执行,因为错误被.CATCHtSQLt.Private_RunTest

因为 tSQLt 用于CATCH捕获错误,所以我怀疑如果不对 tSQLt 进行重大重写,就无法解决这个问题 - 但我在这里询问以防万一其他人找到解决问题的方法。

4

3 回答 3

3

您可以遵循以下方法:

在测试中,将对测试存储过程的调用包装在 try/catch 块中。在 try/catch 块之前,将预期变量设置为 1,将实际变量设置为 0。在测试 catch 块中,检查日志表是否已填充,如果是,则将实际变量翻转为 1。在 catch 块之后编写断言.

CREATE PROC MyTests.[test ExpectException]
AS
    BEGIN
    DECLARE @expected bit = 1;
    DECLARE @actual bit = 0;

    BEGIN TRY
        -- call tested SP, make sure it fails
        CALL SP..;

        -- add safety net, if the SP call doesn't fail then fail the test
        RAISERROR('Fail the test', 16, 1);
    END TRY
    BEGIN CATCH
        -- pseudo code
        IF EXISTS (SELECT 1 FROM log table)
        -> flip @actual to 1
    END CATCH

    EXEC tSQLt.AssertEquals @expected, @actual
END
GO
于 2016-08-09T14:17:54.823 回答
0

对我来说,在 TRY...CATCH 块中调用被测过程和 tSQLt ExpectException proc 似乎已经成功了。

CREATE PROC MyTests.[test ExpectException]
AS
BEGIN
  BEGIN TRY
    -- Call the proc that raises the error
    EXEC offending_stored_proc

    -- Tell tSQLt to expect the exception
    EXEC tSQLt.ExpectException @ExpectedMessage = 'Expected error message', @ExpectedSeverity = NULL, @ExpectedState = NULL;
  END TRY
  BEGIN CATCH
    -- No need to do anything here
  END CATCH
END;

正如预期的那样,如果过程通过该错误消息引发错误,则测试通过。如果未引发错误,则测试失败。

于 2021-06-29T06:51:39.663 回答
0

@Eduard Uta 在我之前到达那里,但无论如何我都会发布这个。


几乎在我发布此内容的同时,我就意识到明显的解决方案是使用自定义TRY...CATCH块,而不是内置的 tSQLt 对象:

CREATE PROC MyTests.[test custom try catch]
AS
BEGIN
    DECLARE @ErrorRaised bit = 0

    BEGIN TRY
        THROW 50001, 'Error message',1
    END TRY
    BEGIN CATCH
        SET @ErrorRaised = 1
    END CATCH

    EXEC tSQLt.AssertEquals 1,@ErrorRaised, 'Error raised'

    EXEC tSQLt.AssertEquals 0,1, '0=1'
END
GO

这是一个测试特定错误消息的示例:

CREATE PROC MyTests.[test custom try catch test message]
AS
BEGIN
    DECLARE @ErrorRaised bit = 0

    BEGIN TRY
        THROW 50001, 'Error message',1
    END TRY
    BEGIN CATCH
        IF ERROR_MESSAGE() = 'Error message'
            SET @ErrorRaised = 1
        ELSE
            THROW
    END CATCH

    EXEC tSQLt.AssertEquals 1,@ErrorRaised, 'Error raised'

    EXEC tSQLt.AssertEquals 0,1, '0=1'
END
GO
于 2016-08-09T14:22:44.620 回答