2

我试图用我的大脑来解决这个问题,但无法让它发挥作用,所以我在这里提出一个小测试用例,希望有人可以向我解释:

首先是一个小测试数据库:

CREATE DATABASE test;
USE test;
CREATE TABLE testA (nr INT)
GO

CREATE TRIGGER triggerTestA
ON testA
FOR INSERT AS BEGIN
  SET NOCOUNT ON;
  IF EXISTS (SELECT nr FROM Inserted WHERE nr > 10)
    RAISERROR('Too high number!', 16, 1);
END;

这是一个 tSQL 测试,用于测试行为:

ALTER PROCEDURE [mytests].[test1] AS
BEGIN
  EXEC tSQLt.FakeTable @TableName = N'testA'
  EXEC tSQLt.ApplyTrigger  
    @TableName = N'testA', 
    @TriggerName ='triggerTestA'
  EXEC tSQLt.ExpectException
  INSERT INTO dbo.testA VALUES (12)
END;

该测试将运行正常 - 但触发器没有执行我想要的操作:阻止用户输入大于 10 的值。此版本的触发器执行我想要的操作:

CREATE TRIGGER triggerTestA
ON testA FOR INSERT AS BEGIN
  SET NOCOUNT ON;
  BEGIN TRANSACTION;
  BEGIN TRY
    IF EXISTS (SELECT nr FROM Inserted WHERE nr > 10)
      RAISERROR('Too high number!', 16, 1);
    COMMIT TRANSACTION;
  END TRY
  BEGIN CATCH
    ROLLBACK TRANSACTION;
    THROW;
  END CATCH;
END;

但是现在测试失败了,说明 A)有一个错误(这是意料之中的!)和 B)没有 BEGIN TRANSACTION 来匹配 ROLLBACK TRANSACTION。我猜这最后一个错误与 tSQLt 围绕事务有关,并且我的触发器以某种方式干扰了它,但肯定不是我所期望的。

有人可以解释一下,也许可以帮我做对吗?

4

1 回答 1

3

tSQLt 目前仅限于在其自己的事务中运行测试,并且如您所见,当您摆弄它的事务时,它的反应是不受欢迎的。

因此,要使该测试正常工作,您需要在测试内部而不是外部跳过回滚。

我建议这种方法:

  1. 从触发器中删除所有事务处理语句。无论如何,您都不需要开始事务,因为触发器总是在一个内部执行。
  2. 如果您发现违规行,请调用执行回滚和 raiserror 的过程
  3. 为您的测试监视该程序

要测试该过程本身,您可以使用 tSQLt.NewConnection

于 2017-09-15T12:53:35.110 回答