Why are [AssemblyInitialize] and [AssemblyCleanup] called twice in the same assembly of test projects?

I thought the goal of these attributes was to run them only once per assembly. I have a simple class as follows:

[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"); } } 

However, when I run the test suite, the Initialize and Cleanup methods at the assembly level are executed twice. Here are the details about my environment:

  • All test classes are in one project / assembly.
  • I have integration and unit tests separated by a namespace.
  • For integration tests, I use MSTextExtensions to allow the rollback of database transactions.
  • I also start / stop the MS SQL Server DTC service, which is required for the rollback feature. I wanted to do this once per run of the test suite (and the best compromise I found was to use assembly level attributes). The code will work, but it is executed twice.
  • If this is important, I also use the Microsoft Moles Framework in some of my tests.

The observed behavior is similar to:

 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? 
+7
unit-testing visual-studio-2008 integration-testing mstest
source share
2 answers

From the MSDN library article:

Attention!

This attribute should not be used by ASP.NET Unit Tests, that is, any tests with the [HostType ("ASP.NET")] attribute. Due to the statelessness of IIS and ASP.NET, the method decorated with this attribute can be called more than once during a test run.


There are several adjustments that you can configure in a test runner. I would just pose the problem with a counter:

 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"); } } 
+5
source share

Well, this answer is a bazillion years late based on the original date of the problem, but ...

I found that if the test agent (QTAgent32.exe) crashes or dies before completing the full sequence, then AssemblyInitialize (and possibly ClassInitialize and TestInitialize) will be called. For example, put this in your [AssemblyCleanup] function and you will see what happens:

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

So, the moral of this story: check your cleaning features to see if there are crashes / corruption. Failures during cleanup are not displayed in the test report because the skip / fail statements are already completed. But the problems that it causes can manifest themselves in other ways.

+1
source share

All Articles