2009-06-10 13 views
19

Scenariusz. Język C#, Testowanie przy użyciu VS2008 Unit framework frameworkUnitTestowanie klas statycznych

Mam klasę statyczną ze statycznym konstruktorem i 2 metody. Mam 4 metody testowe napisane, aby przetestować całą klasę. Mój statyczny konstruktor ma kilka ważnych inicjalizacji.

Teraz, jeśli uruchomię wszystkie 4 przypadki testowe w tandemie, statyczny konstruktor będzie wywoływany tylko na początku. Na końcu każdego przypadku testowego nie ma takiej rzeczy nazywanej statycznym destruktorem, więc informacje o stanie w konstruktorze są przenoszone również do następnego przypadku testowego jednostki jednostkowej Jakie jest obejście tego problemu.

Odpowiedz

11

Najprostszym rozwiązaniem jest dodanie metody "Resetuj" do klasy statycznej, która miałaby równoważne działanie polegające na jej niszczeniu i rekonstrukcji.

Może istnieć ważny powód, dla którego używasz klasy statycznej. Ponieważ jednak statystyka nie gra ładnie z testami jednostkowymi, zwykle szukam alternatywnego projektu.

0

Cóż, nie określiłeś języka, którego używasz, ale jeśli istnieje sposób na otwarcie twojej klasy statycznej z pliku testowego, dodałem do niej fałszywy destruktor, do którego możesz zadzwonić po każdy test. W ten sposób "destruktor" pozostaje w klasie testowej i poza twoim kodem produkcyjnym.

0

Można użyć Typemock's Isolator, która jest w stanie wyśmiać klasy statyczne, więc w każdym teście można "zdefiniować" działanie statyczne.

To jednak nie jest darmowy produkt.

0

Wygląda na to, że próbujesz przetestować konstruktor statyczny. To wygląda na zły pomysł.

Należy rozważyć wyodrębnienie logiki inicjalizacyjnej do oddzielnej (niestatycznej) klasy.

Dla celów dyskusji, załóżmy, że twoja klasa statyczna nazywa się MySingleton i powiedzmy, że tworzysz nową klasę o nazwie MyInitializer, z metodą Execute. Konstruktor statyczny MySingleton może utworzyć instancję MyInitializer i wywołać Execute, która wykonuje całą inicjalizację.

Następnie twój kod produkcyjny może użyć MySingleton i zignorować MyInitializer. Z drugiej strony twoje testy mogą zignorować MySingleton i wesoło stworzyć nową instancję MyInitializer dla każdego testu, za każdym razem uruchamiając nowy start.

1

Bez znajomości użycia klasy, komentowanie tylko użycia jest sprawą nieco trudną, ale nieźle i tak da. Dla mnie powyższe brzmi jak zapach bardziej niż problem z testowaniem.

Klasa statyczna (tak jak singletony) to po prostu zbiór globalnych funkcji/zmiennych, co zwykle jest złe w ujęciu ogólnym. Powiedziałbym, że próba przetestowania problemu z testem jest (chociaż prawdopodobnie najłatwiejsza w tej chwili), tylko naprawia symptomy, ale nie stanowi problemu.

Sugeruję spojrzeć na Desing concidere jeśli naprawdę potrzebujemy klasę statyczną lub jeśli po prostu wydawało się, że najprostszy sposób, aby rozwiązać problem w czasie

5

Chciałbym przenieść z inicjalizacji konstruktor statyczny do metody, która jest wywoływana przez konstruktor.Wykonując tę ​​metodę, można następnie wywołać tę metodę z testów, aby ponownie zainicjować klasę.

public static class MyClass 
{ 
    public static MyClass() 
    { 
     initialize(); 
    } 

    internal static void initialize() 
    { 
     // Do initialization (and cleanup if necessary) 
    } 

    public static void Method1() {} 
    public static void Method2() {} 
} 

W celu wywołania metody wewnętrznych musisz użyć atrybutu InternalsVisibleTo, jak opisano w this blog.

Możesz również ustawić go jako prywatny, ale musisz użyć odbicia, aby go wywołać.

Ale jak powiedział Andrew Shepherd, powinieneś również sprawdzić, czy klasa statyczna jest najlepszym projektem tej klasy.

34
Type staticType = typeof(StaticClassName); 
ConstructorInfo ci = staticType.TypeInitializer; 
object[] parameters = new object[0]; 
ci.Invoke(null, parameters); 

z http://colinmackay.scot/2007/06/16/unit-testing-a-static-class/

+21

Hej, spójrz, odpowiedź na pytanie zamiast "nie rób tego". – deltree

+0

Działa dobrze, jednak musiałem ręcznie zadeklarować statyczny pusty konstruktor w klasie (nawet jeśli normalnie nie jest potrzebny). –

+1

Dlaczego parametry są używane w konstruktorze statycznym? Czy możemy go nazwać 'ci.Invoke (null, null);'? – SerG

0

Dla kompletności wywodu, jeśli trzeba zresetować pole niepubliczne/zmienną klasy statycznej, jest to również możliwe, aby to zrobić za pośrednictwem refleksji.

using System.Reflection; // or Mono.Reflection 

public static class MyClass{ 
    private static string myString; 
} 

var newValue = "Potatoes";    
var field = typeof(MyClass).GetField("myString", BindingFlags.Static | BindingFlags.NonPublic); 
field.SetValue(null, newValue); // the first null is because the class is static, the second is the new value 
Powiązane problemy