Generalnie moment, w którym natkniemy się na potrzebę przetestowania testami jednostkowymi klasy abstrakcyjnej powinien być momentem okrzyku: “refactoring czas zacząć!”. Takie coś teoretycznie nie powinno mieć miejsca; testuje się raczej funkcjonalność faktycznie wykorzystywaną w systemie, a więc bardziej klasy z niej dziedziczące. Odpowiednia hierarchia klas uzupełniona odpowiednią hierarchią testów jednostkowych rozwiązuje problem. Ale wiadomo – ideały sobie, a życie sobie.
Cóż więc zrobić, gdy mamy klasę abstrakcyjną wymagającą przetestowania? Na przykład taką:
Można specjalnie na potrzeby testu zaimplementować klasę dziedziczącą, utworzyć jej instancję i odpowiednią metodę wywołać. Ale możemy również skorzystać z mechanizmów RhinoMocks, którym efektem ubocznym jest taka konstrukcja:
CallAbstract to napisana przeze mnie extension method, poniżej jej implementacja. Przy okazji można przyjrzeć się doda:
1: public static class MockUtils 2: { 3: public static void CallAbstract<T>(Action<T> operation, params object[] argumentsForConstructor) where T : class 4: { 5: var stub = MockRepository.GenerateStub<T>(argumentsForConstructor); 6: stub.Stub(operation).CallOriginalMethod(OriginalCallOptions.NoExpectation); 7: operation(stub); 8: } 9: }
Zaznaczam jeszcze raz, że teoretycznie taka sytuacja nie powinna mieć miejsca. Ale jeśli już ma, to jest to całkiem niezłe jej rozwiązanie “na szybko”.
A nie lepiej skorzystać z PartialMock?
http://ayende.com/Wiki/(S(az3elprzof4y5j2clzmycn55))/Default.aspx?Page=Rhino+Mocks+Partial+Mocks&Code=1&AspxAutoDetectCookieSupport=1
Właśnie one umożliwiają testowanie jakiejś części klasy (włącznie z abstrakcyjnymi).
@Farol:
Czlowiek uczy sie cale zycie a i tak glupi umiera:). Dzieki za linka.