2014-05-12 33 views
-1

我想測試它使用動態SQL這樣一個存儲過程:tsqlt和動態SQL

DECLARE @Sql NVARCHAR(MAX) 

-- create @Sql 

EXEC sp_executesql @Sql 
,N'@NumberOfRollingMonths INT, @FromDate DATETIME, @ToDate DATETIME' 
,@NumberOfRollingMonths = @NumberOfRollingMonths 
,@FromDate = @FromDate 
,@ToDate = @ToDate 

無論我做什麼,我沒有得到測試通過。我正在使用

EXEC tSQLt.FakeTable 

虛假底層數據庫的數據。 tsqlt不適用於動態sql是否是已知的事實?

PS:

更多的代碼:

IF OBJECT_ID('TestDetails', 'U') IS NOT NULL 
    DROP TABLE TestDetails 

CREATE TABLE TestDetails 
(
    Year INT, 
    Period INT, 
    HOURS INT 
) 
INSERT INTO TestDetails (Year, Period, HOURS) 
    SELECT 2004, 1, 10000 UNION ALL 
    SELECT 2004, 2, 100 

IF OBJECT_ID('TestMonthsAndYears', 'U') IS NOT NULL 
    DROP TABLE TestMonthsAndYears 

CREATE TABLE TestMonthsAndYears 
(
    Id INT not null identity(1,1) primary KEY, 
    TheMonth INT NOT NULL, 
    TheYear INT NOT NULL, 
    [Date] DATETIME NOT NULL 
) 

DECLARE @FromDate DATETIME 
DECLARE @ToDate DATETIME 
SET @FromDate = '1900-01-01 00:00:00.000' 
SET @ToDate = '2200-01-01 00:00:00.000' 

INSERT INTO TestMonthsAndYears 
SELECT 
    TOP (DATEDIFF(MONTH, @FromDate, @ToDate) + 1) 
    [TheMonth] = MONTH(DATEADD(MONTH, number, @FromDate)), 
    [TheYear] = YEAR(DATEADD(MONTH, number, @FromDate)), 
    [Date] = DATEADD(month, DATEDIFF(month, 0, DATEADD(MONTH, number, @FromDate)), 0) 
FROM [master].dbo.spt_values 
WHERE [type] = N'P' 

IF EXISTS (SELECT * FROM sys . objects WHERE type = 'P' AND name = 'ToBeRemoved') 
DROP PROCEDURE ToBeRemoved 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
-- ============================================= 
-- Author:  <Author,,Name> 
-- Create date: <Create Date,,> 
-- Description: 
-- ============================================= 
CREATE PROCEDURE [dbo].[ToBeRemoved] 
    @FromDate DATETIME, 
    @ToDate DATETIME, 
    @NumberOfRollingMonths INT 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @Sql NVARCHAR(MAX) 
    DECLARE @SumSql NVARCHAR(MAX) 

    SET @SumSql = N'' 
    IF(@NumberOfRollingMonths > 0) 
     BEGIN 
      SET @NumberOfRollingMonths = @NumberOfRollingMonths * -1; 
     END 

    SET @SumSql = @SumSql + N' SUM(CAST(D.HOURS AS FLOAT)) ' 

    SET @Sql = N' 
    ;WITH SparseValues AS 
    (
     SELECT 
      CAST(CAST(D.YEAR AS VARCHAR(4)) + RIGHT(''0'' + CAST(D.Period AS VARCHAR(2)),2) + ''01'' AS SMALLDATETIME) AS MonthYear, 
      ' + @SumSql + ' AS Value 
     FROM TestDetails D 
     GROUP BY CAST(CAST(D.YEAR AS VARCHAR(4)) + RIGHT(''0'' + CAST(D.Period AS VARCHAR(2)),2) + ''01'' AS SMALLDATETIME) 
    ) 
    ,CompleteValues AS 
    (
     SELECT 
      MY.[Date], 
      ISNULL(Value,0) AS Value 
     FROM TestMonthsAndYears MY 
     LEFT JOIN SparseValues SparseValues ON MY.[Date] = SparseValues.MonthYear 
     WHERE MY.Date BETWEEN @FromDate AND @ToDate 
    ) 
    SELECT 
     S1.[Date], 
     AVG(S2.Value) AS MovingAverage 
    FROM CompleteValues AS S1, CompleteValues AS S2 
    WHERE S2.[Date] > DATEADD(m, @NumberOfRollingMonths,S1.[Date]) AND S2.[Date] <= S1.[Date] 
    GROUP BY S1.[Date] order by date' 

    EXEC sp_executesql @Sql 
     ,N'@NumberOfRollingMonths INT, @FromDate DATETIME, @ToDate DATETIME' 
     ,@NumberOfRollingMonths = @NumberOfRollingMonths 
     ,@FromDate = @FromDate 
     ,@ToDate = @ToDate 
END 


EXEC tSQLt.NewTestClass 'MyTestClass'; 
GO 

CREATE PROCEDURE [MyTestClass].[test very good test] 
AS 
BEGIN 
    -- arrange 
    IF OBJECT_ID('Expected') IS NOT NULL DROP TABLE Expected; 
    IF OBJECT_ID('Actual') IS NOT NULL DROP TABLE Actual; 

    EXEC tSQLt.FakeTable 'dbo', 'TestDetails'; 
    INSERT INTO dbo.TestDetails (Year, period, [HOURS]) 
     SELECT 2004, 1, 30 UNION ALL 
     SELECT 2004, 2, 10 

    CREATE TABLE Expected(Date DATETIME, MovingAverage float) 
    CREATE TABLE Actual(Date DATETIME, MovingAverage float) 
    INSERT INTO Expected (Date, MovingAverage) 
     SELECT '2004-01-01 00:00:00.000', 30 UNION ALL 
     SELECT '2004-02-01 00:00:00.000', 10 

    -- act 
    DECLARE @FromDate DATETIME SET @FromDate = '2004-01-01 00:00:00.000' 
    DECLARE @ToDate DATETIME SET @ToDate = '2004-02-01 00:00:00.000' 
    DECLARE @NumberOfRollingMonths INT SET @NumberOfRollingMonths = -1 

    INSERT INTO Actual 
    EXEC ToBeRemoved @FromDate, @ToDate, @NumberOfRollingMonths 

    EXEC tSQLt.AssertEqualsTable 'Expected', 'Actual', 'Actual result table not equal to expected result table.'; 
END 
+1

包括您正在使用的動態SQL語句,並指定您正在獲取的錯誤。 –

+0

我還沒有使用tsqlt,但根據這裏的結果,你可能想看看http://dbfit.github.io/dbfit/。這是一個非常棒的測試工具,不需要DB中額外的代碼/模式。 –

+0

T-SQL肯定會處理動態SQL。您應該向我們展示實際的代碼,而不是發佈' - create @ Sql'。 –

回答

2

正如其他人評論說,動態SQL確實與tSQLt工作。如果沒有您遇到問題的代碼/測試,很難確定問題可能出在哪裏。

爲了幫助你一起,並幫助恢復tSQLt你的信心,這是一個使用動態SQL一個SP,並調用它的測試,而假表的例子,單元測試的過程:

USE tSQLt_Example 
GO 
--Example table in which we will manipulate data 
CREATE TABLE dbo.DynamicDemo (a INT) 
GO 
INSERT dbo.DynamicDemo (a) VALUES (5) -- This value will be removed by FakeTable 
GO 
--Example proc which uses Dynamic SQL 
CREATE PROC dbo.DynamicAdd (@NoToAdd int) as 
DECLARE @s NVARCHAR(MAX) 
SET @s = 'update dbo.DynamicDemo set [email protected]' 
EXEC sp_executesql @s,N'@NoToAdd int',@NoToAdd = @NoToAdd 
GO 
--create tSQLt class 
exec tSQLt.NewTestClass @ClassName = N'DynamicTest' -- nvarchar(max) 
GO 
--Create test on proc which uses dynamic SQL 
CREATE PROC DynamicTest.[test dynamic sql] 
as 
--Assemble 
EXEC tSQLt.faketable 'dbo.DynamicDemo' 
SELECT TOP 0 * into DynamicTest.Expected FROM dbo.DynamicDemo 
INSERT dbo.DynamicDemo (a) VALUES (4) --Start position 
INSERT DynamicTest.Expected (a) VALUES (7) -- Expected end position 
--Act 
EXEC dbo.DynamicAdd 3 --call proc under test 
--Assert 
EXEC tSQLt.AssertEqualsTable @Actual='dbo.DynamicDemo', @Expected = 'DynamicTest.Expected' 
GO 
--Run Tests 
EXEC tSQLt.Run 'DynamicTest' 
GO 
--Clearup 
DROP TABLE dbo.dynamicDemo 
DROP PROC dbo.DynamicAdd 

這個簡單的例子應該有助於讓你放心,tSQLt本身能夠使用動態SQL就好 - 也許還有另一個依賴性會導致你的問題?如果(如其他人所說的)你可以發佈一個(可運行的)你的問題的例子,我們可以幫助你找出造成你這種痛苦的原因。