最近,我在 StackOverflow 上问(并回答了)一个问题,即为什么单元测试在单独运行时会工作,然后在与整批单元测试一起运行时偶尔会失败。看这里:SQL Server and TransactionScope (with MSDTC): Sporadically can't get connection
一次运行一个单元测试通过,然后一起运行时失败,这是一个典型的迹象,表明代码存在严重错误。
我发现有一点资源泄漏。由于一个微妙的错误导致无法释放到 SQL 服务器的连接,我的连接用完了,测试失败了。 AFAIK,这几乎就像内存泄漏一样;连接是从连接池分配的,并且永远不会释放,就像内存可以分配然后不释放一样。
然而,这确实给我留下了一个令人费解的问题?一次运行一个测试和将它们作为套件运行有什么区别?如果一次运行一个测试时通过,然后一起运行时失败,那么在测试运行之间必须有某种清理发生,只有在一次运行一个测试时才会发生。
我猜想这可能与 .net 垃圾收集器在测试之间做或不做的事情有关。在一种情况下,在测试之间释放连接;在另一种情况下,它们不是。
我该如何解释?
更新:对于那些询问代码细节的人来说,这很简单。我声明一个新的TransactionScope
对象并将其处理在我的 Teardown
中方法。然而,问题测试是一个数据驱动的测试,有 100 个测试用例;被测代码填充了 SqlDataReader
使用 SqlHelper 类从 select 语句中创建对象,然后没有在 SqlDataReader
上调用 close 方法.因为我使用了 SqlHelper 类来获取 SqlDataReader,所以我希望为我处理连接。不是这样!
但澄清一下,我不是在问我的具体情况。我想知道的是:一般来说,测试之间如何释放资源?我想这将是垃圾收集器的一些应用。我想知道垃圾收集器是否仍然可以在下一次测试运行时清理之前的测试(竞争条件?)
更新:我对单元测试的垃圾收集的了解。出于我自己的好奇,我删除了由于连接被 SqlDataReader
打开而失败的单元测试。目的。我尝试添加 System.GC.Collect()
到每次测试结束。这成功地释放了连接,但确实造成了约 50% 的性能损失。
最佳答案
这听起来可行,是的。单元测试框架要求垃圾收集器在测试之间运行并不奇怪。
或者,不同的执行模式可能会在它们一个接一个运行时自然地触发垃圾收集。分析这类事情的麻烦在于它都是非常动态的 - 并且会因测试运行而异。
不要忘记它可能不必释放测试之间的所有连接 - 足以让它们保持运行......
垃圾收集器本身在单元测试中不太可能有任何不同的行为,除非以特定方式配置测试运行器进程。另一方面,是否在调试器中运行测试会影响垃圾收集器的渴望程度等。
关于.net - 垃圾收集器如何处理单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3088255/