在调用 tSQLt.ExpectException 之后,有没有办法在测试中测试其他断言?
Is there a way to test other assertions inside a test after calling tSQLt.ExpectException?
使用 tSQLt 1.0.5873.27393,我正在尝试为存储过程编写一个 tSQLt 测试,在重新抛出错误之前将 CATCH
块中的错误记录到日志 table到呼叫会话。
我可以成功测试使用 tSQLt.ExpectException
重新抛出错误消息,但副作用似乎是调用 tSQLt.ExpectException
后无法测试任何其他断言 - 所以我我无法测试错误是否已写入日志 table.
我能想出的最简单的证明问题的测试是:
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
断言从未执行过,因为错误被 tSQLt.Private_RunTest
内的 CATCH
块捕获。
因为 tSQLt 使用 CATCH
来捕获错误,我怀疑如果不对 tSQLt 进行重大重写就无法解决这个问题 - 但我在这里问是为了以防万一其他人找到了解决该问题的方法。
您可以采用这种方法:
在测试中,将对测试存储过程的调用包装在 try/catch 块中。
在 try/catch 块之前,将预期变量设置为 1,将实际变量设置为 0。
在测试 catch 块中,检查日志 table 是否已填充,如果是,则将实际变量翻转为 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
@Eduard Uta 在我之前到达那里,但无论如何我都会 post。
几乎在我 post 编辑这篇文章时我突然意识到,显而易见的解决方案是使用自定义 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
对我来说,在 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;
正如预期的那样,如果过程通过该错误消息引发错误,则测试通过。如果没有报错,则测试失败。
使用 tSQLt 1.0.5873.27393,我正在尝试为存储过程编写一个 tSQLt 测试,在重新抛出错误之前将 CATCH
块中的错误记录到日志 table到呼叫会话。
我可以成功测试使用 tSQLt.ExpectException
重新抛出错误消息,但副作用似乎是调用 tSQLt.ExpectException
后无法测试任何其他断言 - 所以我我无法测试错误是否已写入日志 table.
我能想出的最简单的证明问题的测试是:
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
断言从未执行过,因为错误被 tSQLt.Private_RunTest
内的 CATCH
块捕获。
因为 tSQLt 使用 CATCH
来捕获错误,我怀疑如果不对 tSQLt 进行重大重写就无法解决这个问题 - 但我在这里问是为了以防万一其他人找到了解决该问题的方法。
您可以采用这种方法:
在测试中,将对测试存储过程的调用包装在 try/catch 块中。 在 try/catch 块之前,将预期变量设置为 1,将实际变量设置为 0。 在测试 catch 块中,检查日志 table 是否已填充,如果是,则将实际变量翻转为 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
@Eduard Uta 在我之前到达那里,但无论如何我都会 post。
几乎在我 post 编辑这篇文章时我突然意识到,显而易见的解决方案是使用自定义 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
对我来说,在 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;
正如预期的那样,如果过程通过该错误消息引发错误,则测试通过。如果没有报错,则测试失败。