简体   繁体   中英

How can I isolate unit tests by class?

I have a number of 'unit tests' (they're really integration tests) in several classes that access a shared resource, and I want each test class to only acquire the resource once (for performance reasons).

However, I'm getting issues when I release the resource in [ClassCleanup] , because that isn't running until all tests are completed.

Here's a simplified example:

using Microsoft.VisualStudio.TestTools.UnitTesting;

static class State
{
    public static string Thing;
}
[TestClass]
public class ClassA
{
    [ClassInitialize]
    public static void Initialize(TestContext ctx)
    {
        State.Thing = "Hello, World!";
    }
    [ClassCleanup]
    public static void Cleanup()
    {
        State.Thing = null;
    }
    [TestMethod]
    public void TestA()
    {
        Assert.IsNotNull(State.Thing); // Verify we have a good state
    }
}
[TestClass]
public class ClassB
{
    [TestMethod]
    public void TestB()
    {
        Assert.IsNull(State.Thing); // Verify we have an uninitialized state
        // Initialize state, do stuff with it
    }
}

On my machine at least, TestB fails because it runs before ClassA has been cleaned up.

I read ClassCleanup May Run Later Than You Think , but that doesn't explain any way to change the behaviour. And I realize I shouldn't depend on test ordering, but it's too expensive to re-acquire the resource for every test, so I want to group them by class.

How can I fix this? Is there a way to force each test class to run as a unit, and make the cleanup occur immediately?

Although ClassCleanup might be unreliable in terms of when it is run, ClassInitialize is not; why not give each testclass that relies on this shared resource a ClassInitialize that cleans up the shared resource of the previous test class (if any), right before acquiring the resource itself?

The only time the shared resource isn't released is for the last test class, but you could handle that with the ClassCleanup because then it doesn't matter anymore when it is run (since there won't be any more test classes following it).

Is there any reason that you cannot make this resource shared by the entire assembly all at once? Make it an internal or public static variable in one of the test classes (or a separate designated class), and refer to it directly from all the test classes. The initialization of the resource will take place in the [AssemblyInitialize] method and the cleanup will take place at the [AssemblyCleanup].

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM