web-dev-qa-db-fra.com

MsTest ClassInitialize et l'héritage

J'ai une classe de base pour mes tests qui se compose de la manière suivante:

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

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

Maintenant, j'essaie de créer un nouveau test qui hérite de la base, avec la signature suivante:

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

La ClassInitialize n'est jamais appelée par les tests enfants ... Quelle est la manière réelle et correcte d'utiliser l'initialisation de test avec l'héritage sur MsTest?

51
Raffaeu

Malheureusement, vous ne pouvez pas réaliser cela de cette façon car la classe ClassInitializeAttribute Class ne peut pas être héritée.

Un attribut hérité peut être utilisé par les sous-classes des classes qui l'utilisent. Puisque la variable ClassInitializeAttribute ne peut pas être héritée, lorsque la classe MyTest est initialisée, la méthode ClassInitialize de la classe MyBaseTest ne peut pas être appelée.

Essayez de le résoudre d'une autre manière. Une méthode moins efficace consiste à définir à nouveau la méthode ClassInitialize dans MyTest et à appeler la méthode de base au lieu de dupliquer le code.

33
chaliasos

Une solution possible consiste à définir une nouvelle classe avec AssemblyInitializeAttribute à la place. Bien entendu, son champ d’application est différent, mais pour moi, il répond à mes besoins (préoccupations transversales qui exigent des réglages identiques pour chaque classe et méthode de test.)

using Microsoft.VisualStudio.TestTools.UnitTesting;

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

Nous savons qu'une nouvelle instance de la classe est construite pour chaque [TestMethod] de la classe au fur et à mesure de son exécution. Le constructeur sans paramètre de la classe de base sera appelé chaque fois que cela se produit. Ne pourriez-vous pas simplement créer une variable statique dans la classe de base et la tester lors de l'exécution du constructeur?

Cela vous aide à ne pas oublier de mettre le code d'initialisation dans la sous-classe.

Pas sûr s'il y a un inconvénient à cette approche ...

Ainsi:

public class TestBase
{
    private static bool _isInitialized = false;
    public TestBase()
    {
        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()
    {
    }
}
1
C.List

Utiliser un constructeur statique sur une classe de base? Il est exécuté une seule fois, de par sa conception, et il n'a pas la limitation étrange en matière d'héritage, comme ClassInitializeAttribute.

0
Mladen B.