tSQLt на SQL Server 2017 AG с включенным DTC - PullRequest
0 голосов
/ 19 ноября 2018

Я получаю следующую ошибку, когда запускаю tSQLt-тесты на SQL Server 2017, настроенном в группе доступности Always On, для которой в группе AG настроено DTC_SUPPORT = PER_DB.Если я отключаю поддержку DTC, она работает нормально.Наша среда требует DTC.Есть ли способ обойти это в tSQLt или есть другой способ настроить SQL так, чтобы DTC и tSQLt работали?

Вот ошибка:

Test Procedure: [xxx].[zzfnCipValidateCustomerAddress].[test '12345' Zip Codes] on DbServer
[zzfnCipValidateCustomerAddress].[test '12345' Zip Codes] failed: (Error) Cannot promote the transaction to a distributed transaction because there is an active save point in this transaction.[16,1]{zzfnCipValidateCustomerAddress.test '12345' Zip Codes,36} (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.Private_RunTest,160})

Вотодин из провальных тестов:

CREATE PROCEDURE [zzfnCipValidateCustomerAddress].[test '12345' Zip Codes]
AS
BEGIN
--Assemble
/*
Test to determine if function is an Inline Table Valued function or not
since this function is being rewritten to be an ITVF function and this test should
pass both versions
*/
DECLARE @IsITVF BIT;

SELECT @IsITVF = IIF(fc.FunctionCount > 0, 1, 0)
FROM
(
    SELECT COUNT(*) AS FunctionCount
    FROM sys.sql_modules AS sm
        JOIN sys.objects AS o
            ON sm.object_id = o.object_id
    WHERE sm.object_id = OBJECT_ID('dbo.fnCipValidateCustomerAddress')
          AND o.type = 'IF' --'IF' = Inline Valued Table Function
) AS fc;

SELECT @IsITVF;


--DROP TABLE IF EXISTS zzfnCipValidateCustomerAddress.TestData;

CREATE TABLE zzfnCipValidateCustomerAddress.TestData
(
    AddressLine1 VARCHAR(100),
    AddressLine2 VARCHAR(100),
    City VARCHAR(50),
    StateAbbr VARCHAR(3),
    ZipCode VARCHAR(9)
);

INSERT INTO zzfnCipValidateCustomerAddress.TestData
(
    AddressLine1,
    AddressLine2,
    City,
    StateAbbr,
    ZipCode
)
VALUES
('Test', NULL, 'Test', 'AZ', '12345');

CREATE TABLE zzfnCipValidateCustomerAddress.Expected
(
    AddressLine1 VARCHAR(100),
    AddressLine2 VARCHAR(100),
    City VARCHAR(50),
    StateAbbr VARCHAR(3),
    ZipCode VARCHAR(9),
    CipExceptionReasonId INT
);

INSERT INTO zzfnCipValidateCustomerAddress.Expected
(
    AddressLine1,
    AddressLine2,
    City,
    StateAbbr,
    ZipCode,
    CipExceptionReasonId
)
VALUES
('Test', NULL, 'Test', 'AZ', '12345', 8);

--Act

IF (@IsITVF = 0)
BEGIN
    SELECT td.AddressLine1,
           td.AddressLine2,
           td.City,
           td.StateAbbr,
           td.ZipCode,
           dbo.fnCipValidateCustomerAddress(td.AddressLine1, td.AddressLine2, td.City, td.StateAbbr, td.ZipCode) AS CipExceptionReasonId
    INTO zzfnCipValidateCustomerAddress.Actual
    FROM zzfnCipValidateCustomerAddress.TestData AS td;
END;
ELSE
BEGIN
    SELECT fcvcat.AddressLine1,
           fcvcat.AddressLine2,
           fcvcat.City,
           fcvcat.StateAbbr,
           fcvcat.ZipCode,
           fcvcat.CipExceptionReasonId
    INTO zzfnCipValidateCustomerAddress.Actual
    FROM zzfnCipValidateCustomerAddress.TestData AS td
        CROSS APPLY dbo.fnCipValidateCustomerAddress(
                                                        td.AddressLine1,
                                                        td.AddressLine2,
                                                        td.City,
                                                        td.StateAbbr,
                                                        td.ZipCode
                                                    ) AS fcvcat;
END;


--Assert

EXEC tSQLt.AssertEqualsTable @Expected = N'zzfnCipValidateCustomerAddress.Expected',
                             @Actual = N'zzfnCipValidateCustomerAddress.Actual',
                             @Message = N'',
                             @FailMsg = N'Zip with value of ''12345'' did not generate a CipExceptionReasonId as expected';

END;

1 Ответ

0 голосов
/ 27 ноября 2018

tSQLt внутренне полагается на точки сохранения транзакций. Точки сохранения не совместимы с распределенными транзакциями.

В настоящее время в tSQLt нет способа изменить обработку транзакций.

Моя рекомендация - настроить выделенную среду CI (непрерывная интеграция), которая предназначена для выполнения вашего автоматизированного набора тестов (и, следовательно, не требует включения AlwaysOn). Независимо от вашей конкретной ситуации, в любом случае это лучшая отраслевая практика.

Однако это не решает процедуры тестирования, которые конкретно относятся к вашей настройке AlwaysOn. Те, которые вы, естественно, должны тестировать в среде с включенным AlwaysOn. В этом случае вы можете использовать команду tSQLt.NewConnection, которая выполняет команду, переданную в отдельном соединении и за пределами транзакции tSQLt.

Имейте в виду, однако, что вы будете нести ответственность за все действия по очистке в этом случае, поскольку все, что выполняется с помощью tSQLt.NewConnection, явно не откатывается tSQLt.

...