C# MsTest 类初始化和继承

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15944504/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 18:33:45  来源:igfitidea点击:

MsTest ClassInitialize and Inheritance

c#mstest

提问by Raffaeu

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 ClassInitializeis never called by the child tests ... What is the real and correctway of using test initialization with inheritance on MsTest?

ClassInitialize永远不会被孩子所谓的测试...什么是真实的,正确的使用测试初始化与MSTest的继承方式?

采纳答案by chaliasos

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

不幸的是,您无法通过这种方式实现这一点,因为ClassInitializeAttribute 类无法被继承。

An inherited attribute can be used by the sub-classes of the classes that use it. Since the ClassInitializeAttributecannot not be inherited, when the MyTestclass is initialized the ClassInitializemethod from the MyBaseTestclass cannot be called.

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

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

尝试用另一种方式解决它。一种效率较低的方法是再次定义ClassInitialize方法MyTest并只调用基本方法而不是复制代码。

回答by C.List

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?

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

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

回答by Dave Sexton

A potential workaround is to define a new class with AssemblyInitializeAttributeinstead. 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.)

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

using Microsoft.VisualStudio.TestTools.UnitTesting;

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

回答by Mladen B.

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.

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

回答by GrayDwarf

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

对于任何只是试图让基本 ClassInit 工作并最终在这里结束的人。

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.

您最终在 ClassInitialize 和 ClassCleanup 中调用的静态方法可以在任何地方,也可以命名为任何名称。