MsTest ClassInitialize and Inheritance

天涯浪子 提交于 2019-12-17 15:59:23

问题


I have a base class for my tests which is composed in the following way:

[TestClass]
public abstract class MyBaseTest
{
   protected static string myField = "";

   [ClassInitialize]
   public static void ClassInitialize(TestContext context)
   {
       // static field initialization
       myField = "new value";
   }
}

Now I am trying to create a new test that inherits from the base, with the following signature:

[TestClass]
public class MyTest : MyBaseTest
{
   [TestMethod]
   public void BaseMethod_ShouldHave_FieldInitialized()
   {
       Assert.IsTrue(myField == "new value");
   }
}

The ClassInitialize is never called by the child tests ... What is the real and correct way of using test initialization with inheritance on MsTest?


回答1:


Unfortunately you cannot achieve this that way because the ClassInitializeAttribute Class cannot be inherited.

An inherited attribute can be used by the sub-classes of the classes that use it. Since the ClassInitializeAttribute cannot not be inherited, when the MyTest class is initialized the ClassInitialize method from the MyBaseTest class cannot be called.

Try to solve it with another way. A less efficient way is to define again the ClassInitialize method in MyTest and just call the base method instead of duplicating the code.




回答2:


A potential workaround is to define a new class with AssemblyInitializeAttribute instead. It has a different scope, obviously, but for me it meets my needs (cross-cutting concerns, which just so happen to require exactly the same settings for every test class and test method.)

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MyTests
{
  [TestClass]
  public sealed class TestAssemblyInitialize
  {
    [AssemblyInitialize]
    public static void Initialize(TestContext context)
    {
      ...
    }
  }
}



回答3:


Use a static constructor on a base class? It's executed only once, by design, and it doesn't have the weird limitation on inheritance, like the ClassInitializeAttribute.




回答4:


For anyone that is just trying to get a basic ClassInit working and ended up here.

Here's an example of what your test class might look like.

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Company.Product.Area
{
    [TestClass]
    public class MyTestSuite : TestInits
    {
        [ClassInitialize]
        public static void MyClassInit(TestContext tc)
        {
            MyInitTestSuite();
        }

        [ClassCleanup]
        public static void MyClassCleanup()
        {
            MyCleanupTestSuite();
        }

        [TestMethod]
        public void My_First_Test()
        {
            ...
        }

        public static void MyInitTestSuite()
        {
            // Setup driver
            // Navigate to site
            // Login
        }

        public static void MyCleanupTestSuite()
        {
            // Quit Driver
        }
    }
}

The static methods you end up calling within ClassInitialize and ClassCleanup can be wherever and named whatever.




回答5:


UPDATE: Added lock to avoid multi-threading issues...

We know that a new instance of the class is constructed for every [TestMethod] in the class as it gets run. The parameter-less constructor of the base class will be called each time this happens. Couldn't you simply create a static variable in the base class and test it when constructor runs?

This helps you to not forget to put the initialization code in the sub-class.

Not sure if there's any drawback to this approach...

Like so:

public class TestBase
{
    private static bool _isInitialized = false;
    private object _locker = new object();

    public TestBase()
    {
        lock (_locker) 
        {
          if (!_isInitialized)
          {
            TestClassInitialize();
            _isInitialized = true;
          }
        }
    }

    public void TestClassInitialize()
    {
        // Do one-time init stuff
    }
}
public class SalesOrderTotals_Test : TestBase
{
    [TestMethod]
    public void TotalsCalulateWhenThereIsNoSalesTax()
    {
    }
    [TestMethod]
    public void TotalsCalulateWhenThereIsSalesTax()
    {
    }
}


来源:https://stackoverflow.com/questions/15944504/mstest-classinitialize-and-inheritance

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!