2008-10-10 13 views
9

Używam MSTEST wewnątrz Visual Studio 2008. W jaki sposób mogę mieć każda metoda testu jednostkowego w pewnej klasie testowej działa tak, jakby był pierwszym testem do uruchomienia, tak aby cały stan globalny został zresetowany przed uruchomieniem każdego testu? Nie chcę, aby wyraźnie oczyścić świat z użyciem TestInitialize, ClassInitialize, AssemblyInitialize itd Na przykład:Jak zmusić MSTEST TestMethod do zresetowania wszystkich singletonów/statyki przed uruchomieniem?

[TestClass] 
public class MyClassTests 
{ 
    [TestMethod] 
    public void Test1() 
    { 
     // The "Instance" property creates a new instance of "SomeSingleton" 
     // if it hasn't been created before. 
     var i1 = SomeSingleton.Instance; 
     ... 
    } 
    [TestMethod] 
    public void Test2() 
    { 
     // When I select "Test1" and "Test2" to run, I'd like Test2 
     // to have a new AppDomain feel so that the static variable inside 
     // of "SomeSingleton" is reset (it was previously set in Test1) on 
     // the call to ".Instance" 
     var i2 = SomeSingleton.Instance; 
     // some code 
    } 

Chociaż similar question pojawiły się na ten temat, to tylko wyjaśnić, że testy nie są uruchamiane równolegle. Rozumiem, że testy są przeprowadzane seryjnie, ale nie ma sposobu, aby wyraźnie wymusić nową AppDomain dla każdej metody (lub coś podobnego do wyczyszczenia wszystkich stanów).

Idealnie, chciałbym określić to zachowanie tylko dla małej części moich testów jednostkowych, aby nie musiałem płacić kary za nowe tworzenie AppDomain dla testów, które nie dbają o stan globalny (zdecydowana większość moich testów).

Odpowiedz

6

W końcu napisałem pomocnika, który używał AppDomain.CreateDomain, a następnie użył odbicia, aby wywołać test jednostki pod inną AppDomain. Zapewnia izolację, której potrzebowałem.

This post na forach MSDN pokazuje, jak poradzić sobie z sytuacją, jeśli masz tylko kilka statystyk, które wymagają zresetowania. It wspomina niektóre opcje (na przykład używając Reflection i PrivateType).

Nadal witam wszelkie dalsze pomysły, szczególnie jeśli brakuje mi czegoś oczywistego na temat MSTEST.

+2

czy masz przykład kodu Jeff? – DevDave

+1

Tak, przykładowy kod: – Harindaka

0

Mieliśmy podobny problem z naszymi MSTests. Poradziliśmy sobie z tym, wywołując funkcję na początku i końcu testów, które tego wymagały.

Przechowujemy datę wygaśnięcia testu w naszej konfiguracji aplikacji. Trzy testy wymagały tej daty, aby znaleźć się w określonym zakresie, aby określić odpowiednie wartości. W jaki sposób konfigurowana jest nasza aplikacja, wartości konfiguracyjne byłyby resetowane tylko wtedy, gdyby w sesji nie była przypisana wartość. Stworzyliśmy więc dwie nowe prywatne funkcje statyczne - jedną, która jawnie ustawi wartość konfiguracji na określoną datę, a drugą, aby usunąć tę datę z sesji po uruchomieniu testu. W naszych trzech testach nazwaliśmy te dwie funkcje. Po uruchomieniu następnego testu aplikacja widzi pustą wartość daty i ponownie pobiera ją z pliku konfiguracyjnego.

Nie jestem pewien, czy to jest pomocne, ale w ten sposób rozwiązaliśmy nasz podobny problem.

+0

Wygląda na to, że możesz użyć [TestInitialize] w twojej klasie testowej? –

0

Myślę, że szukasz atrybutów TestIntialize i atrybutu TestCleanUp. Oto blog MSDN pokazujący zlecenie wykonania: link text

+0

Dzięki za odpowiedź. Szukałem czegoś, co oczyści świat bez konieczności wyraźnego usuwania każdej zmiennej, ale nie jestem pewien, czy to możliwe. –

3

Dodaj pomocnika w swoich testach, który używa odbicia, aby usunąć pojedynczą instancję (możesz dodać metodę resetowania również do singletonu, ale byłbym zaniepokojony jej użyciem). Coś jak:

public static class SingletonHelper { 
      public static void CleanDALFactory() 
      { 
        typeof(DalFactory) 
         .GetField("_instance",BindingFlags.Static | BindingFlags.NonPublic) 
         .SetValue(null, null); 
      } 
} 

Zadzwoń do tego w swojej metodzie TestInitialize. [Wiem, że to "oczyszczanie świata", ale musisz napisać tę metodę tylko raz w programie pomocniczym na singleton, jest to bardzo trywialne i daje wyraźną kontrolę]

+0

Dziękuję za odpowiedź. Myślę, że będę musiał użyć kombinacji Reflection do iteracji po statycznych polach i mniej więcej tego, co opisujesz tutaj. Coś jak "NullifyStaticFields (Type t)", aby można go było ponownie wykorzystać –