单元/集成测试和恢复数据库

时间:2011-12-13 12:49:45

标签: c# sql unit-testing integration-testing snapshot

在C#中使用自动化测试用例,我们需要在每次测试后恢复数据库快照。问题是,当运行多个测试时,它会失败,因为“当其他用户正在使用数据库时,无法更改数据库状态。”

我们在恢复之前使用SqlConnection.ClearAllPools();,但在第四次测试之后,它不会再次恢复运行,并且似乎池停止清除。 (为什么四个?见编辑2)

如何让这更可靠?

修改

也许我应该提供有关该系统的更多信息。这些是服务的单元集成测试。测试引用服务dll(没有服务引用,我们直接访问服务方法)。因此,除了在每个测试块之后恢复数据库快照之外,测试中没有SQL。

这是一项服务,因此我们无法完全管理连接。我们有一个中心点,我们在其中创建数据库对象,我们从中获取DbCommands来执行存储过程。

在SQL studio中使用sp_who2,我观察到以下内容:前四个测试块(每个块由ClearAllPools()和快照恢复分隔),数据库有一个会话,但是从第五个测试块开始,有三个针对它的会话。 (为什么?这可能是问题的线索。)(快照恢复打开了与主数据库的附加连接。)所有打开的连接都有状态休眠,等待命令,甚至是阻止快照恢复连接的命令。

编辑2

为什么五个?我认为测试用例会随机执行,但我错了。我找到了罪魁祸首。打开多个连接,系统仅使用最后一个连接,其他连接处于挂起状态,直到退出后才会清除。

3 个答案:

答案 0 :(得分:6)

在恢复快照之前,请以单用户模式设置数据库:

   ALTER DATABASE <mydb> SET SINGLE_USER WITH ROLLBACK IMMEDIATE

如果您不希望终止打开的连接,可以通过在没有回滚选项的情况下运行它来使命令等待

   ALTER DATABASE <mydb> SET SINGLE_USER

这是一个黑客攻击,但是很难让你的快照恢复一致地工作。 (一旦被咬,两次害羞。)

答案 1 :(得分:5)

我使用不同的方法。我在一个事务中运行测试,该事务将在每个测试结束时处理(回滚)。 这样您就不需要在每个测试会话中丢弃数据库,因为db总是“干净”。 在C#中,您可以创建一个TransactionScope并在测试后进行处理,或者(更好)如果您使用xUnit.net,则可以使用AutoRollback属性。

答案 2 :(得分:0)

我们正在做同样的事情。在每次测试之前从备份恢复数据库:

ALTER DATABASE <dbname> SET OFFLINE WITH ROLLBACK IMMEDIATE
DROP DATABASE <dbname>
RESTORE DATABASE <dbname> FROM DISK= ...

对于数据库不存在的情况,我们还使用

检查数据库
IF DB_ID (N'<dbname>') IS NOT NULL

希望这有帮助