I had a test class with two unit tests in them which worked fine, until I started refactoring to get common setup/teardown functionality moved into methods with TestInitialize/TestCleanup attributes applied.
Then the weirdness started. I started seeing this:
The tests don't run; don't pass or fail; and no details as to why. Check out the yellow highlighted areas. |
I began searching the internet trying to find someone who ran into the same problem. I found many results where developers complained of the TestInitialize methods swallowing exceptions and moving on, so I started down that path in my own code, trying to discover if there was an exception I was missing that was being eaten and causing the entire class to fail.
The only problem was, when I commented all code within the bodies of the TestInitialize/TestCleanup methods, I still ended up with the same results.
??? |
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class TestInitializeAttribute : Attribute
AllowMultiple = false... which makes sense. So my code had two problems:
- My base class' method for TestInitialize needed to be made virtual so it could be overridden in classes that inherit from it to allow for overriding (and calling back to the base so both get their jobs done.)
- My child class' method was named different, so I needed to go make it match and override.
Once I fixed these problems for both the init and cleanup methods, the tests went back to working accurately.
Bottom Line: When doing unit testing with base test classes that perform common setup functionality, make sure to have your Setup/Teardown or Initialize/Cleanup methods marked virtual in the base class, so they can be overridden in the sub-classes. Then override those methods in the sub-class, making sure to call back to the base appropriately.
Example (MSTest):
public class CommonTestSetupBase
{
[TestInitialize]
public virtual void TestSetup()
{
// do common setup work for all that inherit
}
[TestCleanup]
public virtual void TestTeardown()
{
// do common cleanup work for all that inherit
}
}
//=================
[TestClass]
public class UnitTestedClassTests : CommonTestSetupBase
{
[TestInitialize]
public override void TestSetup()
{
base.TestSetup();
// do common setup for this class
}
[TestCleanup]
public override void TestTeardown()
{
// do common cleanup for this class
base.TestTeardown();
}
}
I knew I wouldn't remember this if I bump into it again, so I had to document it here... I wish I had more time to go into more detail, but I hope this will be enough to help you and I in the future when we meet this problem again.