我有一个代码库,它在很多情况下都使用了静态变量,这在某些情况下是有意义的,例如标记某些东西自启动以来已经运行过一次,等等。
当然,这可能会导致单元测试出现问题,因此突然出现顺序问题,并且对此类方法的测试结果可能取决于之前是否已命中其他代码等。我对 TestTools.UnitTesting 的理解是每当我运行一组单元测试时,同一项目中的任何单元测试都在同一进程中运行,因此从测试到测试都保持任何静态状态,而单元测试项目边界也意味着进程边界,因此,如果我运行来自项目 A 的 3 个测试,然后来自项目 B 的第四个测试,状态从 1>2>3 维护(无论它们运行的顺序如何)但是 4 是原始的,任何静态状态都是默认的。
所以现在我的问题有两个:
1) 当测试在一个组中运行(全部运行或选择运行)时,单元测试项目与流程具有 1:1 的关系,我的评估是否正确,或者是否存在我遗漏的更多细微差别?
2) 无论如何,如果我有一个测试肯定需要新鲜的默认静态状态用于它使用和测试的自定义对象,我是否有比给它自己的测试项目更优雅的创建它的选择?
最佳答案
静态实际上不是每个进程,而是每个应用程序域,由 AppDomain 类表示。一个进程可以有多个 AppDomain。 AppDomains 有自己的静态特性,可以为部分受信任的代码提供沙盒,并且可以卸载,允许在不重新启动应用程序的情况下热交换同一程序集的新版本。
您的测试运行器可能会为每个测试程序集创建一个新的 AppDomain,因此每个程序集都有自己的静态变量。您可以创建一个 AppDomain 来即时执行相同的操作。这对于纯单元测试来说通常不是很好,但我不得不使用“粗鲁”的库,这些库执行各种无法清除或重置的静态初始化和缓存。在这些类型的集成场景中,它非常有用。
您可以使用这个助手来运行一个简单的委托(delegate):
public static class AppDomainHelper
{
public static void Run(Action action)
{
var domain = AppDomain.CreateDomain("test domain");
try
{
domain.DoCallBack(new CrossAppDomainDelegate(action));
}
finally
{
AppDomain.Unload(domain);
}
}
}
一个警告是传递给 Run
的委托(delegate) action
不能有任何捕获的变量(如来自 lambda)。这是行不通的,因为编译器会生成一个不可序列化的隐藏类,因此它无法通过 AppDomain 边界。
关于c# - 单元测试使用静态变量的 C#/.NET 类(单元测试进程隔离),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24335174/