【发布时间】:2011-03-06 12:28:28
【问题描述】:
最近,我在 StackOverflow 上询问(并回答)了一个问题,即为什么一个单元测试在单独运行时会起作用,然后在与整批单元测试一起运行时偶尔会失败。见这里:SQL Server and TransactionScope (with MSDTC): Sporadically can't get connection
单元测试在一次运行一个时通过,然后在一起运行时失败,这是代码出现严重问题的典型迹象。
我发现有一点资源泄漏。由于一个微妙的错误导致无法释放与 SQL 服务器的连接,我的连接用完了并且测试失败了。 AFAIK,这几乎就像内存泄漏一样工作;连接是从连接池中分配的,永远不会被释放,就像内存可以分配然后不被释放一样。
但是,这确实给我留下了一个令人费解的问题?一次运行一个测试和将它们作为一个套件运行有什么区别?如果测试在一次运行一个时通过,然后在一起运行时失败,则必须在测试运行之间进行某种清理,只有在一次运行一个测试时才会发生。
我猜想这可能与 .net 垃圾收集器在测试之间做什么或不做什么有关。在一种情况下,测试之间的连接被释放;在另一种情况下,它们不是。
我该如何解释?
更新:对于那些询问代码细节的人来说,这很简单。我在我的 Setup 方法中声明了一个新的 TransactionScope 对象,并在我的 Teardown 方法中处理它。然而,问题测试是一个包含 100 个测试用例的数据驱动测试;被测代码使用 SqlHelper 类从 select 语句中填充了一个 SqlDataReader 对象,然后没有在 SqlDataReader 上调用 close 方法。因为我使用 SqlHelper 类来获取 SqlDataReader,所以我希望为我处理连接。不是这样!
但为了澄清,我不是在问我的具体情况。我想知道的是:一般来说,测试之间的资源是如何释放的?我想这将是垃圾收集器的一些应用。我想知道垃圾收集器是否仍然可以在下一个测试运行时清理上一个测试(竞争条件?)
更新:我对单元测试垃圾收集的了解。 出于好奇,我删除了由于SqlDataReader 对象保持打开连接而失败的单元测试。我尝试将System.GC.Collect() 添加到每个测试的末尾。这成功地释放了连接,但确实会造成约 50% 的性能损失。
【问题讨论】:
-
如果您因为在测试之间没有释放足够多的连接而导致连接用完,我怀疑您的拆卸方法有问题。当一次运行它们时,操作系统会负责一些拆除,但作为一个套件运行,您的资源使用会持续更长时间。
-
也许您只是需要更多
Dispose或Close来电?
标签: .net sql unit-testing garbage-collection