Результаты FakeFunction на основе теста - PullRequest
0 голосов
/ 09 апреля 2019

Я использую tSqlt для модульного тестирования хранимой процедуры. Этот сохраненный процесс присоединяется к табличной функции, функция не принимает параметров, а результаты фильтруются с помощью предложения join on.

Я пишу несколько тестов для сохраненного процесса. Есть ли способ подделать функцию таким образом, чтобы я мог возвращать разные результаты в зависимости от выполняемого теста.

Единственное решение, которое я могу придумать, - создать подделку для каждого теста, что возможно, но немного более чем неуклюже.

Я полагаю, что идеальным решением была бы какая-то переменная, представленная в tsqlt, которая позволила бы мне определить, в каком тесте я нахожусь, и использовать какой-то оператор case или что-то в этом роде.

Ответы [ 2 ]

1 голос
/ 10 апреля 2019

Для этого я использую следующую процедуру.Это не идеально, но работает:

CREATE PROCEDURE [tSQLt].[FakeFunction2]
    @FunctionName VARCHAR(200)
  , @SchemaName   VARCHAR(200) = 'dbo'
  , @tmpTableName VARCHAR(200)
AS
    BEGIN
      DECLARE @Params VARCHAR(2000);
        DECLARE @NewName VARCHAR(MAX) = @FunctionName + REPLACE(CAST(NEWID() AS VARCHAR(100)), '-', '');
        DECLARE @FunctionNameWithSchema VARCHAR(MAX) = @SchemaName + '.' + @FunctionName;
        DECLARE @RenameCmd VARCHAR(MAX) = 'EXEC sp_rename ''' + @FunctionNameWithSchema + ''', ''' + @NewName + ''';';
        DECLARE @newTbleName VARCHAR(200) = @SchemaName + '.tmp' + REPLACE(CAST(NEWID() AS VARCHAR(100)), '-', '');
        DECLARE @newTblStmt VARCHAR(2000) = 'SELECT * INTO ' + @newTbleName + ' FROM ' + @tmpTableName;

        EXEC tSQLt.SuppressOutput @command = @newTblStmt;

        SELECT @Params = p.params
          FROM
               (   SELECT      DISTINCT (   SELECT p1.name + ' ' + type1.name + b.brk + ',' AS [text()]
                                              FROM sys.types              type1
                                              JOIN sys.parameters         p1 ON p1.system_type_id = type1.system_type_id
                                             CROSS APPLY
                                                   (   SELECT CASE WHEN type1.name LIKE '%char' OR type1.name = 'varbinary' THEN
                                                                       REPLACE(
                                                                           '(' + CAST(p1.max_length AS VARCHAR(5)) + ')', '-1', 'MAX')
                                                                   WHEN type1.name IN ('decimal', 'numeric') THEN
                                                                       '(' + CAST(p1.precision AS VARCHAR(5)) + ', '
                                                                       + CAST(p1.scale AS VARCHAR(5)) + ')'
                                                                   WHEN type1.name IN ('datetime2') THEN
                                                                       '(' + CAST(p1.scale AS VARCHAR(5)) + ')'
                                                                   ELSE ''
                                                              END AS brk) b
                                             WHERE p1.object_id = p.object_id
                                             ORDER BY p1.parameter_id
                                            FOR XML PATH('')) [parameters]
                     FROM      sys.objects    AS o
                     LEFT JOIN sys.parameters AS p ON p.object_id      = o.object_id
                     LEFT JOIN sys.types      AS t ON t.system_type_id = p.system_type_id
                    WHERE      o.name = @FunctionName AND o.schema_id = SCHEMA_ID(@SchemaName)) [Main]
         CROSS APPLY
               (SELECT LEFT(Main.[parameters], LEN(Main.[parameters]) - 1) params)              AS p;

        EXEC tSQLt.SuppressOutput @command = @RenameCmd;

        DECLARE @newFunctionStmt VARCHAR(MAX) = '';

        SET @newFunctionStmt = 'CREATE FUNCTION [' + @SchemaName + '].[' + @FunctionName + '](' + COALESCE(@Params,'') + ')';
        SET @newFunctionStmt = @newFunctionStmt + ' RETURNS TABLE AS RETURN (SELECT * FROM ' + @newTbleName + ');';

        EXEC tSQLt.SuppressOutput @command = @newFunctionStmt;
    END;

и использование:

INSERT INTO #table
  (col1
  , col2
  , col3)
VALUES
  ('a', 'b', 'c'),
  ('d', 'e', 'f');

EXEC tSQLt.FakeFunction2 @FunctionName = 'function_name'
                        , @SchemaName = 'dbo'
                        , @tmpTableName = '#table';

теперь с любым переданным параметром этой функции он всегда будет возвращать значения из #table временная таблица

0 голосов
/ 10 апреля 2019

Я подумал об одном потенциальном решении.

Я создаю таблицу в схеме класса теста и заполняю ее результатами, которые я хочу вернуть для каждого теста.

CREATE TABLE testcalass.fakefunction_Results
(
    ID INT,
    Value NUMERIC(12, 5)
)
GO

CREATE FUNCTION testcalass.fakefunction()
RETURNS @results TABLE
(
    ID INT,
    Value NUMERIC(12, 5)
)
BEGIN
    INSERT INTO @results
    SELECT ID, Value FROM testcalass.fakefunction_Results
END
GO

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

...