为什么在同一个测试项目程序集中调用[AssemblyInitialize]和[AssemblyCleanup]两次?

时间:2010-10-27 04:04:12

标签: visual-studio-2008 unit-testing mstest integration-testing

我认为这些属性的全部目的是每个程序集只运行一次。我有一个简单的课程如下:

[TestClass]
public class AssemblyIntegrationTestSetup
{
    public AssemblyIntegrationTestSetup() { }
    public TestContext TestContext { get; set; }

    [AssemblyInitialize]
    public static void SetupIntegrationTests(TestContext context)
    {
         WindowsServiceService.Instance.StartService("Distributed Transaction Coordinator");
    }

    [AssemblyCleanup]
    public static void TeardownIntegrationTests()
    {
          WindowsServiceService.Instance.StopService("Distributed Transaction Coordinator");
    }

}

但是,当我运行测试套件时,程序集级Initialize和Cleanup方法执行两次。以下是关于我的环境的详细信息:

  1. 所有测试类都在同一个项目/程序集中。
  2. 我有以命名空间分隔的集成和单元测试。
  3. 对于集成测试,我使用MSTextExtensions来允许回滚数据库事务。
  4. 我也在启动/停止MS SQL Server DTC服务,这是回滚功能所必需的。我希望每个测试套件运行一次(我发现最好的折衷方案是使用汇编级属性)。代码可以工作,但它会执行两次。
  5. 如果重要的话,我在一些测试中也使用了Microsoft Moles Framework。
  6. 观察到的行为类似于:

    AssemblyInitialize         
    
    Class1.TestInitialize
    Class1.TestMethod1
    Class1.TestCleanup
    
    AssemblyInitalize         <-- //This shouldn't be happening right?
    
    Class2.TestInitialize
    Class2.TestMethod1
    Class2.TestCleanup
    
    Class2.TestInitialize
    Class2.TestMethod2
    Class2.TestCleanup
    
    Class5.TestInitialize
    Class5.TestMethod1
    Class5.TestCleanup
    
    Class7.TestInitialize
    Class7.TestMethod1
    Class7.TestCleanup
    
    //More random bouncing around then...
    
    AssemblyCleanup 
    AssemblyCleanup           <-- //This shouldn't be happening right?
    

3 个答案:

答案 0 :(得分:6)

来自MSDN Library文章:

  

重要

     

不应使用此属性   ASP.NET单元测试,即任何测试   使用[HostType(“ASP.NET”)]属性。   因为IIS的无状态特性   和ASP.NET,一个装饰的方法   此属性可能会被调用更多   每次试运行一次。


你可以在测试跑步者中调整很少的旋钮。我只想用一个柜台解决这个问题:

private int InitCount;

[AssemblyInitialize]
public static void SetupIntegrationTests(TestContext context)
{
     if (InitCount++ == 0) {
         WindowsServiceService.Instance.StartService("Distributed Transaction Coordinator");
     }
}

[AssemblyCleanup]
public static void TeardownIntegrationTests()
{
      if (--InitCount == 0) {
          WindowsServiceService.Instance.StopService("Distributed Transaction Coordinator");
      }
}

答案 1 :(得分:1)

嗯,根据最初的问题日期,这个答案已经晚了几年......但是......

我发现测试代理(QTAgent32.exe)在完成序列完成之前崩溃或死亡,然后再次调用AssemblyInitialize(可能是ClassInitialize和TestInitialize)。例如,将它放在[AssemblyCleanup]函数中,您将看到行为发生:

Process p = AutotestShared.RunProcess("cmd", "/c taskkill /t /f /im QTAgent32.exe", true);
p.WaitForExit();

所以这个故事的寓意是:检查你的清理功能,看是否有任何崩溃/腐败。清理期间的故障不会显示在测试报告中,因为通过/失败断言已经完成。但它引起的问题可能会以其他方式出现。

答案 2 :(得分:0)

就我而言,这是QTAgent32.exe进程的不当行为,导致[AssemblyInitialize]被执行两次。重新启动构建并执行我的代码的主机,为我解决了这个问题。