tSQLt В Private_RunTest также произошла ошибка ROLLBACK

Всякий раз, когда я использую ExpectException, я получаю следующую ошибку: (Также произошла ошибка ROLLBACK -> Текущая транзакция не может быть принята и не может быть откатлена до точки сохранения. Откат всей транзакции.{Private_RunTest,140})

Похоже, что tSQLt пытается выполнить ROLLBACK после того, как MSSQL уже выполнил ROLLBACK из-за RAISERROR. Я обернул следующий оператор SELECT и SET в Private_RunTest следующим оператором IF, и это, похоже, решило проблему.

IF ISNULL(@ExpectException,0) <> 1 
  BEGIN
    SELECT @Msg = COALESCE(@Msg, '') + ' (There was also a ROLLBACK ERROR --> ' + 
                  COALESCE(ERROR_MESSAGE(), '') + '{' + 
                  COALESCE(ERROR_PROCEDURE(), '') + ',' + 
                  COALESCE(CAST(ERROR_LINE() AS NVARCHAR), '') + '})';
    SET @Result = 'Error';
  END

Это действительно ошибка и / или подходящее исправление?

2 ответа

Вы, вероятно, не используете блоки TRY/CATCH в своем тесте tsqlt.

Сообщение об ошибке "ROLLBACK ERROR -> Текущая транзакция не может быть зафиксирована и ее нельзя откатить до точки сохранения. Откатить всю транзакцию." Можно воспроизвести следующим образом:

1) Создайте триггер, который выдает ошибку и откатывается следующим образом:

CREATE TRIGGER [dbo].[MyTable_IUDTR] ON [dbo].[MyTable]
    AFTER INSERT, UPDATE, DELETE
AS 
BEGIN

  BEGIN TRY
      RAISERROR('MyError', 16, 1)
  END TRY

  BEGIN CATCH
      THROW;
  END CATCH

END
GO

2) Создайте тест tsqlt, чтобы проверить возвращаемое сообщение об ошибке:

CREATE PROC [ut_MyTable_IUDTR].[test that the error is returned]
AS
BEGIN

  DECLARE @ErrorMsg VARCHAR(50)

  EXEC tsqlt.FakeTable @TableName = 'MyTable'
  EXEC tsqlt.ApplyTrigger 'MyTable', 'MyTable_IUDTR'

  INSERT INTO dbo.MyTable
          ( FirstName, LastName )
  VALUES  ( N'John',N'Smith')

  SET @ErrorMsg = ERROR_MESSAGE()

  EXEC tSQLt.AssertEqualsString @Expected = 'MyError', @Actual = @ErrorMsg

END
GO

3) Запустите тест:

EXEC [tSQLt].Run 'ut_MyTable_IUDTR.test that the error is returned'

4) Вы получаете следующую ошибку:

    There was also a ROLLBACK ERROR --> The current transaction cannot be committed and cannot be rolled back to a savepoint. Roll back the entire transaction.

ИСПРАВЛЕНИЕ:

Измените тест tsqlt, чтобы включить блоки TRY/CATCH следующим образом:

ALTER PROC [ut_MyTable_IUDTR].[test that the error is returned]
AS
BEGIN

  DECLARE @ErrorMsg VARCHAR(50)

  EXEC tsqlt.FakeTable @TableName = 'MyTable'
  EXEC tsqlt.ApplyTrigger 'MyTable', 'MyTable_IUDTR'

  BEGIN TRY
      INSERT INTO dbo.MyTable
              ( FirstName, LastName )
      VALUES  ( N'John',N'Smith')
  END TRY

  BEGIN CATCH
      SET @ErrorMsg = ERROR_MESSAGE()
  END CATCH

  EXEC tSQLt.AssertEqualsString @Expected = 'MyError', @Actual = @ErrorMsg

END
GO

Вы можете использовать SET XACT_ABORT ON в вашем тесте tsqlt

CREATE PROC [testClass]. [Test foo]
КАК
НАЧАТЬ
  SET XACT_ABORT ON
  EXEC tsqlt.AssertEquals @Expected = 1, @Actual = 0
КОНЕЦ

Не делай этого.

Вы получите сообщение, подобное этому

[testClass].[test foo] failed: (Error) Expected: <1> but was: <0> (There was also a ROLLBACK ERROR --> The current transaction cannot be committed and cannot be rolled back to a savepoint. Roll back the entire transaction.{Private_RunTest,160})

Другие вопросы по тегам