zdG*_*eau 10 sql-server tdd tsqlt
faketable功能没有重新分配到正常.我现在使用faketable的所有表都包含我在单元测试插入中使用的值的内容.它是很多表,它使我的数据库无用.请帮助解决这个问题或至少是它的原因.这让我非常担心在CI部署过程中使用它,可能更重要的是在我们的本地开发工作中.
这只能处理将表放回原位(因为这是 OP 和我都遇到的问题),但是使用放置表的行可能会使其与其他对象类型一起工作。
DECLARE @cmd nvarchar(MAX) = '';
WITH x AS (
SELECT TOP 10000
PL.Id AS Id
,PARSENAME(PL.OriginalName,1) AS OriginalName
,ISNULL(SO.name,'') AS name
,QUOTENAME(SCHEMA_NAME(ISNULL(SO.schema_id,1))) AS SchemaName
,ISNULL(SEP.major_id,-1) AS major_id
FROM tSQLt.Private_RenamedObjectLog PL
LEFT JOIN sys.objects SO
ON ObjectId = object_id
LEFT JOIN sys.extended_properties SEP
ON SEP.major_id = SO.object_id
AND SEP.name = 'tSQLt.FakeTable_OrgTableName'
ORDER BY SO.create_date DESC
)
SELECT @cmd = @cmd
+ CASE WHEN x.name = '' OR OriginalName = x.name
THEN N'DELETE tSQLt.Private_RenamedObjectLog WHERE Id = ' + CAST(x.Id AS nvarchar) + N';'
ELSE N'DROP '
+ N'TABLE' --Replace this with a CASE statement to deal with other object types
+ N' ' + SchemaName + '.' + QUOTENAME(x.OriginalName) + '; '
+ NCHAR(13) + NCHAR(10) + N'EXEC sp_rename ''' + SchemaName + N'.'
+ QUOTENAME(x.name) + N''',''' + OriginalName + N''';'
+ NCHAR(13) + NCHAR(10) + N'IF OBJECT_ID('''+SchemaName + N'.' + QUOTENAME(x.name)+N''') IS NULL'
+ NCHAR(13) + NCHAR(10) + N'BEGIN'
+ CASE WHEN x.major_id != -1
THEN NCHAR(13) + NCHAR(10) + N' EXEC sp_dropextendedproperty ''tSQLt.FakeTable_OrgTableName'',''SCHEMA'','''
+ PARSENAME(SchemaName,1) + N''',''TABLE'',''' + OriginalName + N''';'
ELSE ''
END
+ NCHAR(13) + NCHAR(10) + N' DELETE tSQLt.Private_RenamedObjectLog WHERE Id = ' + CAST(x.Id AS nvarchar) + N';'
+ NCHAR(13) + NCHAR(10) + N'END'
END
+ NCHAR(13) + NCHAR(10)
+ NCHAR(13) + NCHAR(10)
FROM x;
--/* <-Remove leading dashes to execute
PRINT @cmd;
--*/EXEC (@cmd);
Run Code Online (Sandbox Code Playgroud)
您的某个测试或代码可能会使事务处于无法回滚的状态.这通常会导致在结果中看到一个或多个带有"错误"(而不是"成功"或"失败")的测试.
在这些情况下,FakeTable操作不会回滚,并且表处于伪造状态.
在封面下,FakeTable重命名表并创建它的新副本.重命名发生时,操作将记录在tSQLt.Private_RenamedObjectLog中.
例如,您可以使用以下代码重现tSQLt无法正常回滚的错误:
EXEC tSQLt.NewTestClass 'SOF_Example'
GO
CREATE TABLE SOF_Example.MyTable (i INT);
GO
INSERT INTO SOF_Example.MyTable (i) VALUES (5);
GO
CREATE PROCEDURE SOF_Example.[test fake a table]
AS
BEGIN
EXEC tSQLt.FakeTable 'SOF_Example.MyTable';
INSERT INTO SOF_Example.MyTable (i) VALUES (12);
COMMIT;
END;
GO
EXEC tSQLt.Run 'SOF_Example';
Run Code Online (Sandbox Code Playgroud)
您可以使用此代码查看重命名的表日志:
SELECT OriginalName, SCHEMA_NAME(schema_id) + '.' + name AS [Name of Renamed Table], create_date
FROM tSQLt.Private_RenamedObjectLog
JOIN sys.objects ON ObjectId = object_id;
Run Code Online (Sandbox Code Playgroud)
如果您多次重新执行测试,则每个伪造表的日志中可能有许多条目.您可以使用create_date来帮助确定哪个包含原始数据.
现在,尽管如此:最好不要在必须保留数据的数据库中编写和执行测试用例.最好的方法是使用不包含用户数据的数据库(最多只包含基本配置数据).您应该从空白数据库开发和单元测试.填充数据库应该用于其他形式的测试,例如集成,可用性,性能等.
我对 tSQLt 有同样的问题,并且能够使用表 tSQLt.Private_RenamedObjectLog 的内容恢复所有内容
该表由 tSQLt 框架维护,并证明包含被伪造的原始表的名称,以及临时(即伪造)表的 SQL ObjectID。使用以下查询生成伪造表的列表,以及它们临时重命名的名称(tSQLt 生成的随机名称,例如tSQLt_tempobject_3815e077fea84c7c):
SELECT
ObjectId, OriginalName,
OBJECT_SCHEMA_NAME(ObjectId) AS SchemaName,
OBJECT_NAME(ObjectId) AS TemporaryName
FROM
tSQLt.Private_RenamedObjectLog
Run Code Online (Sandbox Code Playgroud)
刷新 SSMS 中的对象资源管理器显示确实存在具有这些随机名称的表,并且它们确实包含我的原始数据(哇!!)。
然后我做了以下事情:
ROLLBACK TRANSACTION一下以防万一。它没有。将表(使用临时名称)重命名回其原始名称,对每个表使用此名称:
EXEC sp_rename 'schema.tempname', 'originalname'
在我知道我的表回来后,使用清除了表 tSQLt.Private_RenamedObjectLog
DELETE FROM tSQLt.Private_RenamedObjectLog
制作一个自动生成恢复脚本的程序会很容易!也许 tSQLt 中已经有一个——有人知道吗?