【问题标题】:FakeFunction Results based on Test基于测试的 FakeFunction 结果
【发布时间】:2019-04-09 20:54:12
【问题描述】:

我正在使用 tSqlt 对存储过程进行单元测试。这个存储过程连接到一个表值函数,该函数不带参数,结果通过 join on 子句过滤。

我正在为存储过程编写多个测试。有没有办法伪造函数,以便我可以根据正在运行的测试返回不同的结果。

我能想到的唯一解决方案是每次测试都创建一个假的,这是可能的,但有点笨拙。

我想一个理想的解决方案是在 tsqlt 中公开某种变量,这将允许我确定我在哪个测试中并使用某种 case 语句或其他东西。

【问题讨论】:

    标签: tsqlt


    【解决方案1】:

    我为此使用以下程序。这并不理想,但可以工作:

    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 临时表的值

    【讨论】:

      【解决方案2】:

      我想到了一种可能的解决方案。

      我在测试类模式中创建了一个表,并用我希望每次测试返回的结果填充它。

      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
      

      所以基本上,我可以在组装部分的测试顶部填充函数结果。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-15
        • 1970-01-01
        • 2013-11-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多