2013-04-04 10 views
5

Mam konfiguracji klasa w następujący sposób:Czy Microsoft Fakes obsługuje metody abstrakcyjne na podkładce?

public abstract FooClass { 
    public FooClass() { 
     // init stuff; 
    } 

    public void RandomMethod() { 
     // do stuff; 
    } 

    public abstract WhatIWantToShim(); 
} 

Co chcę zrobić, to ustawić WhatIWantToShim na ShimFooClass tak:

ShimFooClass.AllInstances.WhatIWantToShim =() => Boo(); 

mogę ustawić RandomMethod dobrze,

ShimFooClass.AllInstances.RandomMethod =() => CalculatePi(); 

Wygląda jednak na to, że wygenerowana ShimFooClass nie tworzy właściwości WhatIWantToShim we właściwości AllInstances obiektu ShimFooClass.

Spojrzałem na http://msdn.microsoft.com/en-us/library/hh549176.aspx#bkmk_shim_basics, ale nie widzę tam żadnych abstrakcyjnych metod. Jedyne, co widzę, o którym mowa, nie jest obsługiwane, to finalizatory. Czy ktoś wie, co się tutaj dzieje i czy ten scenariusz jest obsługiwany?

+0

Czy można utworzyć metodę ustawiającą właściwość? – RedJandal

+0

Nie śledząc ciebie, nie ma właściwości dla abstrakcyjnej metody stworzonej na klasie shim. To jest problem. –

Odpowiedz

4

Ahhh .... porażka

Interfejsy i metody abstrakcyjne. Stuby zapewniają implementacje interfejsów i abstrakcyjnych metod, które można wykorzystać w testowaniu. Podkładki nie mogą współpracować z instrumentami i metodami abstrakcyjnymi, ponieważ nie mają ciał metod.

http://msdn.microsoft.com/en-us/library/hh549175(v=vs.110).aspx

Update: co można zrobić, choć jest stubbing podkładkę.

using (ShimsContext.Create()) 
{ 
    bool wasAbstractMethodCalled = false; 
    var targetStub = new StubFooClass() 
    { 
     WhatIWantToShim01 =() => wasAbstractMethodCalled = true 
    }; 
    var targetShim = new ShimFooClass(targetStub); 
    targetShim.AllInstances.RandomMethod =() => CalculatePi(); 
    FooClass target = targetShim.Instance; 
    target.WhatIWantToShim(); 
    Assert.IsTrue(wasAbstractMethodCalled, "The WhatIWantToShim method was not called."); 
} 

Ponieważ podkładka nie może obsłużyć detouring metodę WhatIWantToShim i okrojoną może po prostu utworzyć nową instancję klasy skrótowej i ustawić obsługi objazd dla abstrakcyjnej metody. (Uwaga: 01 oznaczony na końcu WhatIWantToShim został dodany automatycznie dla mnie, gdy Fałki zostały wygenerowane w moim rzeczywistym kodzie).

Następnie wystarczy przekazać instancję kodu pośredniczącego do konstruktora klasy shim i odsunąć w razie potrzeby.

0

Odpowiadam tutaj, ponieważ jestem pewien, że inna odpowiedź nie odpowiedziała na pytanie, a przyszłe wyszukiwania zwracają przydatne informacje.

Po pierwsze nie można podkładać interfejsów. Metoda abstrakcyjna jest odpowiednikiem interfejsu. Ponadto nie ma powodu do tego.

{ 
    bool wasAbstractMethodCalled = false; 
    var targetStub = new StubFooClass() 
    { 
     WhatIWantToShim01 =() => wasAbstractMethodCalled = true 
    }; 
    ShimFooClass.AllInstances.RandomMethod = @class => targetStub.CalculatePi(); 
    targetStub.WhatIWantToShim(); 
    Assert.IsTrue(wasAbstractMethodCalled, "The WhatIWantToShim method was not called."); 
} 

Powyższa wersja jest uproszczoną wersją poprzedniej odpowiedzi i po prostu wywoła akcję, którą właśnie przypisałeś. To prawdopodobnie nie jest twój zamiar.

Pamiętaj, DLACZEGO skierujesz. Podsłuchujesz, gdy chcesz uniknąć efektów wywołania metody w testowanej metodzie. Metoda abstrakcyjna nie może mieć ciała, a zatem nie może wpływać na nic. Byłoby to przydatne tylko na zajęciach dla dzieci, gdzie shim byłby dostępny w pierwszej kolejności.

Jedyną sytuacją, w której możesz mieć problem, jest sytuacja, w której trzecia klasa potajemnie przechowuje instancję klasy abstrakcyjnej i tworzy ją z klasą podrzędną. Nie możesz tego udawać. Jest to jednak straszny projekt; instancja powinna pochodzić z jakiejś metody (którą można podpiąć) lub przekazać (ponieważ DI jest dobrą rzeczą!) albo abstrakcja jest bezwartościowa i równie dobrze możesz uznać instancję za typ dziecka, ponieważ w żaden sposób nie używasz abstrakcji.

Powiązane problemy