类初始化和继承

本文关键字:继承 初始化 | 更新日期: 2023-09-27 18:08:41

我有一个测试的基类,它由以下方式组成:

[TestClass]
public abstract class MyBaseTest
{
   protected static string myField = "";
   [ClassInitialize]
   public static void ClassInitialize(TestContext context)
   {
       // static field initialization
       myField = "new value";
   }
}

现在我尝试创建一个继承基测试的新测试,具有以下签名:

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

ClassInitialize从未被子测试调用…什么是真实和正确的方法在MsTest上使用继承的测试初始化?

类初始化和继承

不幸的是你不能这样做,因为ClassInitializeAttribute类不能被继承。

继承的属性可以被使用它的类的子类使用。由于ClassInitializeAttribute不能被继承,当MyTest类初始化时,不能调用MyBaseTest类中的ClassInitialize方法。

试着用另一种方法解决它。一种效率较低的方法是在MyTest中再次定义ClassInitialize方法,并且只调用基方法,而不是重复代码。

一个潜在的解决方法是用AssemblyInitializeAttribute定义一个新类。显然,它有不同的作用域,但对我来说,它满足了我的需求(横切关注点,这恰好需要每个测试类和测试方法的完全相同的设置)

using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MyTests
{
  [TestClass]
  public sealed class TestAssemblyInitialize
  {
    [AssemblyInitialize]
    public static void Initialize(TestContext context)
    {
      ...
    }
  }
}

ClassInitialize和ClassCleanup属性有一个参数:

[ClassInitialize(InheritanceBehavior.BeforeEachDerivedClass)]
public static void ClassInitialize(TestContext context)
{
   // gets called once for each class derived from this class
   // on initialization
}
[ClassCleanup(InheritanceBehavior.BeforeEachDerivedClass)]
public static void Cleanup()
{
   // gets called once for each class derived from this class
   // on cleanup
}

在基类上使用静态构造函数?按照设计,它只执行一次,并且没有像ClassInitializeAttribute那样对继承有奇怪的限制。

更新:添加锁以避免多线程问题…

我们知道,类中的每个[TestMethod]在运行时都会构造一个新的类实例。每次发生这种情况时都将调用基类的无参数构造函数。难道不能简单地在基类中创建一个静态变量,并在构造函数运行时进行测试吗?

这可以帮助您不要忘记将初始化代码放在子类中。

不确定这种方法是否有缺点…

一样:

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()
    {
    }
}