7
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

4 回答 4

16

问题是 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
于 2013-02-19T19:19:04.150 回答
1

在一些朋友的帮助下,我能够解决这个问题!我将 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].[Test usp_MyStuff_Get Get my stuff] failed: (Error) 更新或插入视图或函数“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]'
于 2019-07-31T18:25:41.877 回答
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
于 2019-07-02T16:06:45.470 回答
0

正如塞巴斯蒂安所说,动态 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')
于 2019-07-25T15:57:23.510 回答