2012-05-23 8 views
12

Próbuję Setup powrót wywołanie metody wydłużania i otrzymuję:wynik Instalator dla wywołania metody wydłużania

SetUp : System.NotSupportedException : Expression references a method that does not belong to the mocked object: m => m.Cache.GetOrStore<String>("CacheKey",() => "Foo", 900)

Wydaje się, że problem z odwoływania się do metody GetOrStore na obiekt Cache, który jest metodą rozszerzenia.

Kod się kompiluje, ale test kończy się niepowodzeniem z tym wyjątkiem.

Co muszę zrobić, aby skonfigurować wynik takiej metody rozszerzenia?

+2

Czy kpiłeś z metod/właściwości użytych w metodzie rozszerzenia? –

+0

Metoda rozszerzenia jest metodą statyczną w klasie statycznej. Nie oczekuję, że 'GetOrStore' będzie rzeczywiście wywoływany, więc kpiny z metod, które wywołają, nie powinny być konieczne, prawda? –

+0

'GetOrStore' wywołuje' Get' i 'Insert' na obiekcie' Cache'. Metoda 'GetOrStore' nie powinna być w rzeczywistości wykonywana, ponieważ jest to sztuczka ... –

Odpowiedz

19

Metody rozszerzeń nie mogą być wyśmiewane tak jak metody instancji, ponieważ nie są zdefiniowane na typie wyśmiewanym. Są one zdefiniowane w innych klasach statycznych. Ponieważ nie można po prostu kpić z nich, zamiast tego należy udawać wszystkie metody/właściwości używane przez metodę rozszerzenia.

Jest to przykład tego, jak metody rozszerzeń ściśle wiążą Twój kod z innymi klasami. Cokolwiek robisz, twoja klasa zależy od tych statycznych metod. Nie można tego wyśmiać i przetestować w odosobnieniu. Sugeruję refaktoryzację kodu, aby przenieść te metody do ich własnych klas, jeśli istnieje jakakolwiek logika wewnątrz.

+1

Dzięki za pomoc. Postanowiłem zrezygnować z metody rozszerzania i wykorzystać mój własny ICache jako sugerowany. Teraz wszystko wygląda znacznie prościej. –

5

Moq nie może symulować metod statycznych, dlatego nie będzie można kpić z rozszerzenia GetOrStore.

Zamiast po prostu kpić z metod Get i obiektu Cache.

+0

Dzięki @FlorianGreinacher. Jedynym problemem jest to, że nie mogę ustawić "Get", ponieważ nie jest to wirtualne. –

0

Jest to możliwe, choć nie ładne ... Zakładam, że wewnątrz metody rozszerzenia znajduje się wewnętrzny obiekt pamięci podręcznej lub odniesienie do jakiejś pamięci podręcznej. Możesz użyć odbicia, aby zastąpić wewnętrzny obiekt do przechowywania pamięci podręcznej. W teście pojawi się coś takiego:

IFixture fixture = new Fixture().Customize(new AutoMoqCustomization()); 

Mock<ICache> internalCache = new Mock<ICache>(); 
internalCache.Setup(i => i.Get<String>("CacheKey")).Returns("Foo"); 

var cacheExtension = typeof(CacheExtensions); 
var inst = cacheExtension.GetField("_internalCache", BindingFlags.NonPublic | BindingFlags.Static); 
inst.SetValue(cacheExtension, internalCache.Object); 

Należy zauważyć, że ten kod nie jest testowany, ale powinien wyjaśnić podstawowy pomysł.

Powiązane problemy