【问题标题】:MSTest & AppDomainsMSTest & AppDomains
【发布时间】:2010-09-20 08:36:53
【问题描述】:

在我的一些项目中,我注意到在 VSTS2008 下执行单元测试期间,其 VSTestHost 的内存消耗会增加。由于我的解决方案中有很多测试,它最终会导致 OutOfMemroyException。 这对我来说看起来很奇怪,因为我确信 MSTest 会为每个单元测试创​​建一个新的 AppDomain。否则它将如何重置静态字段? 但是,如果为每个测试创建 AppDomain,则内存不应泄漏。但确实如此。

所以问题是:VS 是否应该为每个测试类创建 AppDomain?如果是,那么我该如何检查它是否做到了。 我尝试通过 ProcessExplorer 和 Performance 管理单元进行跟踪。在测试运行期间,“Total appdomain unloaded”的值始终为 0。

【问题讨论】:

标签: visual-studio unit-testing mstest


【解决方案1】:

MsTest 为每个测试程序集创建一个应用域,除非您使用 noisolation,在这种情况下没有 AppDomain Isolation。

如果您发现泄漏,可能是在您的测试代码或产品代码中。确保你没有把东西塞进字典里然后放在那里。

【讨论】:

  • +1,每个程序集的应用程序域。但是 - 它还会为每个测试创建一个新的测试类实例,因此它实际上应该 GC 字段。我在 MS 测试中也有一些记忆问题,我不知道为什么。我认为测试运行器存在一些问题。
  • 每个测试在测试类实例上+1。 [ClassInitialize] 是静态的。
【解决方案2】:

我认为单元测试引擎不会为每个测试创建一个新的 AppDomain。由于创建 AppDomain 是一项相对昂贵的操作,因此对每个测试都这样做会大大减慢单元测试的执行速度!

Visual Studio 2008 使用名为 vstesthost.exe 的单独可执行文件来运行单元测试。 VS 与 vstesthost.exe 通信(我不知道它是怎么做的)告诉它要运行哪些测试。 vstesthost.exe 将执行结果返回给显示这些结果的 VS。

如果您在运行单元测试时遇到 OutOfMemoryExceptions,我会说这是一个强有力的指标,表明您的测试代码实际上并没有清理干净。您确定您没有保留非托管对象/内存的句柄吗?我建议在性能分析下运行您的单元测试(您可以通过在“测试视图”下找到单元测试,右键单击它,然后选择“创建性能会话”来做到这一点)。这至少可以对您的对象分配有所了解。

【讨论】:

    【解决方案3】:

    我对每个单元测试都有单独的 AppDomain 是错误的。

    以下是证据: 单身人士

    public class Singleton
    {
        public static Singleton Instance = new Singleton();
    
        private Guid _token;
        private Singleton()
        {
            _token = Guid.NewGuid();
        }
    
        public Guid Token
        {
            get { return _token; }
        }
    }
    

    还有两个测试:

    [TestClass]
    public class UnitTest2
    {
        [TestMethod]
        public void TestMethod1()
        {
            Console.WriteLine(Singleton.Instance.Token);
        }
    }
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            Console.WriteLine(Singleton.Instance.Token);
        }
    }
    

    在执行两个测试期间输出相同的 guid。

    【讨论】:

      【解决方案4】:

      在大型测试运行中看到了同样的问题。我的理论如下。在这种情况下,内存耗尽是由于 MSTest 测试结果文件是 XML 的事实。因此,在序列化到磁盘之前,它需要将所有日志结果保存在内存中,直到测试运行结束。 XML 万岁 :-)

      我不久前以connect issue 发布了这个问题,它应该已在 MSTest 10(64 位)中得到修复,但由于我们正在移动的所有其他问题,我还无法验证这一点到 VS2010 和 .NET 4.0。

      【讨论】:

        【解决方案5】:

        处置单例的唯一方法是处置 appDomain。单例是对自身的静态保持,所以它基本上是一个循环引用。真正的单例在 appdomain 消失之前不会被释放。

        【讨论】:

          【解决方案6】:

          这似乎在 MSTest 2010 中没有得到解决。我遇到了很多类似的问题。为什么垃圾回收在单元测试中不起作用?

          我的理解是 UT 框架负责处理所有已执行的测试,但对于我们在代码中拥有的一些单例模式似乎并非如此。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-12-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多