2014-05-12 85 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就好 - 也许还有另一个依赖性会导致你的问题?如果(如其他人所说的)你可以发布一个(可运行的)你的问题的例子,我们可以帮助你找出造成你这种痛苦的原因。