tSQLt, триггеры и тестирование
Я пытался обернуть это вокруг себя, но не могу заставить его работать, поэтому я привожу небольшой тестовый пример, и, надеюсь, кто-нибудь сможет мне это объяснить:
Сначала небольшая тестовая база данных:
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. Я предполагаю, что эта последняя ошибка связана с транзакцией tSQL t, и что мой триггер как-то мешает этому, но это точно не то, что я ожидаю.
Может ли кто-нибудь объяснить, и, возможно, помочь мне сделать это правильно?
2 ответа
В настоящее время tSQLt ограничен для запуска тестов в своей собственной транзакции и, как вы видели, реагирует, как вы уже не приветствовали, когда вы возитесь с его транзакцией.
Итак, чтобы этот тест работал, вам нужно пропустить откат внутри теста, но не снаружи.
Я предлагаю этот подход:
- Удалите все операторы обработки транзакций из триггера. В любом случае вам не нужно начинать транзакцию, поскольку триггеры всегда выполняются внутри нее.
- Если вы обнаружите строку с нарушением, вызовите процедуру, которая выполняет откат и ошибку
- Шпион, что процедура для вашего теста
Чтобы протестировать саму процедуру, вы можете использовать tSQLt.NewConnection
Как насчет добавления транзакций таким образом, чтобы разрешить вложение? Ниже я создаю транзакцию, только если я еще не участвую в транзакции.
CREATE <PROCEDURE or TRIGGER>
BEGIN
DECLARE @TranName VARCHAR(32),
@IsTranCreatedByThis BIT = 0;
SET @TranName = REPLACE((CAST(NEWID() AS VARCHAR(36))),'-','');
IF @@TRANCOUNT = 0
BEGIN
SET @IsTranCreatedByThis = 1;
BEGIN TRAN
END
SAVE TRAN @TranName
BEGIN TRY
-- Your transaction statement here
IF (@IsTranCreatedByThis = 1)
BEGIN
COMMIT TRAN
END
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
BEGIN
IF (@IsTranCreatedByThis = 1)
BEGIN
ROLLBACK TRAN
END
ELSE
BEGIN
ROLLBACK TRAN @TranName
END
END
THROW;
END CATCH
END