.net 使用自动配置的localdb进行单元测试;我怎么清理?
我已经配置了一个.mdf文件和一个localdb连接字符串,以便在单元测试中使用,如下所示:.net 使用自动配置的localdb进行单元测试;我怎么清理?,.net,sql-server,localdb,.net,Sql Server,Localdb,我已经配置了一个.mdf文件和一个localdb连接字符串,以便在单元测试中使用,如下所示: <connectionStrings> <add name="TestData" providerName="System.Data.SqlClient" connectionString="Data Source=(localdb)\v11.0; AttachDBFilename='|DataDirectory|\TestData.mdf'; Integrated S
<connectionStrings>
<add name="TestData" providerName="System.Data.SqlClient" connectionString="Data Source=(localdb)\v11.0; AttachDBFilename='|DataDirectory|\TestData.mdf'; Integrated Security=True"/>
</connectionStrings>
一旦我为测试正确配置了部署文件,这将非常有效:将.mdf的副本附加到LocalDB的默认实例,并且SqlClient连接到该实例而无需任何配置。它只是工作
但是我以后怎么收拾呢?在我的本地机器上,我可以定期使用SSM手动分离旧的测试数据库,但在CI服务器上,显然最好让单元测试自行清理
是否有类似的自动逻辑方法使localdb数据库与实例分离?我就是这样删除localdb数据库的。我不喜欢的是.mdf也被删除了。我首先将其复制到tem目录并使用该副本创建db,从而克服了这一问题
var sc = new Microsoft.SqlServer.Management.Common.ServerConnection(your localDB SqlConnection here);
var server = new Microsoft.SqlServer.Management.Smo.Server(sc);
server.KillDatabase(dbName here);
希望这有帮助
菲尔像这样:
// ProjectPath/bin/Debug/dbfile.mdf
[TestInitialize]
public void SetUp()
{
AppDomain.CurrentDomain.SetData(
"DataDirectory", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ""));
}
如果您谈论的是单元测试,比如xUnit,那么您可以向测试本身添加一些属性,以便对任何涉及数据库的测试进行回滚 实际上,它在企业级事务中运行测试。这使得每个测试的数据都保持稳定,并且不需要模拟数据库;它可以有效地成为验收测试 例如,在xUnit中: [事实] [自动回滚] public void应插入有效数据 { //排列:假设有一个对象sut支持insert, //你有一些数据 //行为: int key=sut.Insertdata; //断言: Assert.Truekey>0,应返回主键; 插入的var=sut.Getkey; Assert.Equaldata,inserted,CompareAllButKey; } 仅供参考:sut是测试中的情况或测试中的受试者 在上查看这篇文章可能会有所帮助。在那篇文章的结尾还有其他一些不错的链接
顺便说一句,我使用了xUnit作为示例,但其他测试框架在控制回滚方面也有类似的属性。是的,但您可能不需要它 我目前正在使用一个过程,即按照wbx911/Tim Post在其答案中的方式连接数据库。但是,如果要附加原始数据库的副本(例如,由项目/解决方案构建创建的副本),则不需要断开连接。如果没有连接到数据库,它将在下一次测试运行时被覆盖 如果连接了大量数据库副本,或者只是不想清理连接的所有内容,那么可以使用以下存储过程,连接到localDb实例的主数据库,这是我个人使用的一个示例:
CREATE PROCEDURE [dbo].[DettachTestDatabases]
AS
BEGIN
DECLARE @imax INT,
@i INT
DECLARE @Name VARCHAR(255)
DECLARE @DbsToDrop TABLE(RowID INT IDENTITY ( 1 , 1 ),
name VARCHAR(255)
)
INSERT @DbsToDrop
SELECT [name]
FROM [master].[sys].[databases]
WHERE
--Remove all local dbs with *SomeText*.mdf or SomeOtherTextin name
(name like '%SomeText%.mdf' or name like '%SomeOtherText%')
-- Exclude VS test dbs (add more as required...)
and (name not like '%TESTS.%');
SET @imax = @@ROWCOUNT
SET @i = 1
WHILE (@i <= @imax)
BEGIN
SELECT @Name = name
FROM @DbsToDrop
WHERE RowID = @i
EXEC master.dbo.sp_detach_db @dbname = @Name;
PRINT 'Dettatched ' + @Name;
SET @i = @i + 1;
END --while
END --sp
GO
我使用一个命名约定来确定要删除哪些dbs,因此使用类似的语句。VisualStudio附加了两个db,或者至少我认为它们属于VS,用于管理测试结果,我不想分离这些db,因此不喜欢这种情况。这里有一个master.dbo.sp_detach_db,它按名称进行跟踪,因此您实际上只需要引用名称,但由于localdb名称可能有点疯狂,因此查找将非常有用
在测试结束时,我还没有实现自动化,因为我觉得没有必要这样做,因为覆盖工作正常,但我可以随时在SSMS中执行它。但是,如果您觉得有必要,您只需要管理清理代码对SP的调用
连接dbs的过程有些昂贵。我选择了cleanup方法/SP,它删除所有变量数据并重新设定表的种子,以使数据库处于一致状态,这非常快,而不是重新连接数据库
如果你发现有什么改进的地方,我真的很想知道 您正在使用的单元测试框架是否允许您在MS测试、NUnit 3和XUnit中附加清理方法?如果是这样的话,您可以连接下面这样的东西,以便在测试结束时自动分离数据库
public static void CleanUp()
{
using (var connection = new SqlConnection(ConnectionString))
{
connection.Open();
using (var command = connection.CreateCommand())
{
var sql = "DECLARE @dbName NVARCHAR(260) = QUOTENAME(DB_NAME());\n" +
"EXEC('exec sp_detach_db ' + @dbName + ';');";
command.CommandText = sql;
command.ExecuteNonQuery();
}
}
}
为什么不模拟您的依赖关系并创建一个真正的单元测试呢?“就目前情况而言,您所做的是一个集成测试。”丹尼尔曼承认这是正确的,但可以接受的是,它非常接近。我只是没有时间为db构建一个真正的模拟。有人提出了一个解决方案吗?我想使用localdb进行集成测试,但事实证明,基于localdb可以附加一个DB而不是分离它的愚蠢方式,这是非常困难的。在不进行大量时间投资的情况下,使用某些技术(如Entity Framework)进行模拟的价值是有限的。不,这很好。我将.mdf设置为部署文件,因此每次测试都会将其复制为新文件,因此删除mdf是可以的。我试试看。@BenCollins帮你做的?当数据库名是自动的时,如何获取它?@SimonHartcher No。获取生成的数据库名对我来说也是一个阻塞问题。从那以后,我或多或少地放弃了整个机制,转而使用正确模拟的存储库接口,以避免对运行的依赖
ning DB。@BenCollins我发现可以从SqlConnection中获取数据库名称,但这对我来说并不管用。我想使用repository模式,但由于一些原因我无法使用。这并不能以任何方式回答这个问题。