tSQLt.FakeTable似乎不适用于具有常量/派生字段的视图

时间:2013-02-19 19:07:36

标签: sql tsqlt

exec tSQLt.SetFakeViewOn 'dbo.viewWithIssues';
GO
CREATE PROCEDURE    TestChanges.[Test Data]
AS
BEGIN
...

exec tSQLt.FakeTable 'dbo.viewWithIssues', @identity=1, @ComputedColumns=1, @Defaults=1;
INSERT INTO dbo.viewWithIssues (clock_id, IsTerminated)
VALUES  ('1111', '0'), ('2222', '1'), ('3333', '1')

...
END
GO
exec tSQLt.SetFakeViewOff 'dbo.viewWithIssues';
GO

然后在调用过程后继续填充#Actual和#Expected。 它返回的错误是:更新或插入视图或函数'dbo.viewWithIssues'失败,因为它包含派生或常量字段。

有谁知道怎么解决这个问题?

4 个答案:

答案 0 :(得分:12)

问题是SQL Server在编译时捕获了这个问题,因此永远不会执行FakeTable。这就是SetFakeViewOn应该捕获的,但它目前无法可靠地工作。现在没有真正干净的方法,然后将插入和更新放入动态SQL:

CREATE PROCEDURE    TestChanges.[Test Data]
AS
BEGIN
...

exec tSQLt.FakeTable 'dbo.viewWithIssues', @identity=1, @ComputedColumns=1, @Defaults=1;
EXEC('INSERT INTO dbo.viewWithIssues (clock_id, IsTerminated)'+
'VALUES  (''1111'', ''0''), (''2222'', ''1''), (''3333'', ''1'');');

...
END

答案 1 :(得分:0)

我建议您使用insert语句创建一个存储过程,并在exec tSQLt.FakeTable之后调用它。.

CREATE PROCEDURE    TestChanges.[Test Data]

AS
BEGIN
...
exec tSQLt.FakeTable 'dbo.viewWithIssues', @identity=1, @ComputedColumns=1, @Defaults=1;

execute TestChanges.[Insert into viewWithIssues]

...
END

答案 2 :(得分:0)

正如Sebastian所说,动态SQL是必经之路。如果有很多列(特别是需要单引号的文本/日期类型),我将使用以下模式:

  1. 创建一个与视图具有相同定义的临时表
  2. 填充临时表
  3. 使用动态SQL将数据从临时表复制到伪造的视图中
-- #1
SELECT TOP(0) *
INTO #tempView
FROM dbo.viewWithIssues

-- #2
INSERT INTO #tempView (clock_id, IsTerminated)
VALUES  ('1111', '0'), ('2222', '1'), ('3333', '1')

-- #3
EXEC ('INSERT INTO dbo.viewWithIssues SELECT * FROM #tempView')

答案 3 :(得分:0)

在一些朋友的帮助下,我得以解决此问题! 我将tSQLt.FakeTable命令移至Setup.sql,因为tSQLt在该模式中的其他测试之前先运行它。我们通过在同一SQL查询中运行FakeTable命令和INSERT INTO命令来发现此异常。像这样:

EXEC [dbServername].tSQLt.FakeTable @TableName='vw_viewname', @SchemaName='dbo';
INSERT INTO     [dbServername].dbo.vw_myView
                (Column1, Column2, Column3, Column4, Column5, Column6, Column7)
VALUES          ( '100513','C','2018-12-13','2019-03-25','2014-10-27',' ',40.500,'3');

那会导致错误: [TestSchemaName]。[测试usp_MyStuff_Get得到我的东西]失败:(错误)由于视图或函数'dbServername.dbo.vw_myView'包含派生字段或常量字段而导致更新或插入失败。

这有效:

CREATE PROCEDURE [TestSchemaName].[Setup]
AS
BEGIN
    IF @@TRANCOUNT > 0
        BEGIN
            EXEC [dbServername].tSQLt.FakeTable @TableName='vw_viewname', @SchemaName='dbo'
        END
    ELSE
        BEGIN
             RAISERROR('Procedure was run without tsqlt.Run. Aborting procedure', 16, 1)
        END

END
CREATE PROCEDURE [TestSchemaName].[Test usp_MyStuff_Get Get my stuff]
AS
BEGIN
    IF @@TRANCOUNT > 0
        BEGIN
            --EXEC [dbServername].tSQLt.FakeTable @TableName='vw_viewname', @SchemaName='dbo'
            --I moved the line above to the Setup.sql

            INSERT INTO     [dbServername].dbo.vw_myView
                            (Column1, Column2, Column3, Column4, Column5, Column6, Column7)
            VALUES          ( '100513','C','2018-12-13','2019-03-25','2014-10-27',' ',40.500,'3')
       END
    ELSE
        BEGIN
            RAISERROR('Procedure was run without tsqlt.Run. Aborting procedure', 16, 1)
        END
END
GO

发布项目,然后从SSMS运行:

EXEC tsqlt.run '[TestSchemaName].[Test usp_MyStuff_Get Get my stuff]'