Mam już istniejący interfejs ...
public interface ISomeInterface
{
void SomeMethod();
}
i rozszerzyłem tę intreface za pomocą miksera ...
public static class SomeInterfaceExtensions
{
public static void AnotherMethod(this ISomeInterface someInterface)
{
// Implementation here
}
}
Mam klasę, która to nazywa, którą chcę przetestować ...
public class Caller
{
private readonly ISomeInterface someInterface;
public Caller(ISomeInterface someInterface)
{
this.someInterface = someInterface;
}
public void Main()
{
someInterface.AnotherMethod();
}
}
i test, w którym chciałbym kpić z interfejsu i zweryfikować wywołanie metody rozszerzenia ...
[Test]
public void Main_BasicCall_CallsAnotherMethod()
{
// Arrange
var someInterfaceMock = new Mock<ISomeInterface>();
someInterfaceMock.Setup(x => x.AnotherMethod()).Verifiable();
var caller = new Caller(someInterfaceMock.Object);
// Act
caller.Main();
// Assert
someInterfaceMock.Verify();
}
Uruchomienie tego testu generuje jednak wyjątek ...
System.ArgumentException: Invalid setup on a non-member method:
x => x.AnotherMethod()
Moje pytanie brzmi: czy istnieje dobry sposób na wyśmiewanie połączenia miksera?
c#
unit-testing
mocking
extension-methods
moq
Russell Giddings
źródło
źródło
Odpowiedzi:
Nie można "bezpośrednio" mockować metody statycznej (stąd metody rozszerzającej) przy użyciu frameworka mockującego. Możesz wypróbować Moles ( http://research.microsoft.com/en-us/projects/pex/downloads.aspx ), bezpłatne narzędzie firmy Microsoft, które wdraża inne podejście. Oto opis narzędzia:
Możesz używać Moles z dowolnym środowiskiem testowym (jest to niezależne od tego).
źródło
Użyłem Wrappera, aby obejść ten problem. Utwórz obiekt opakowujący i przekaż swoją wyimaginowaną metodę.
Zobacz Mocking Static Methods for Unit Testing autorstwa Paula Irwina, zawiera ładne przykłady.
źródło
Odkryłem, że muszę odkryć wnętrze metody rozszerzającej, dla której próbowałem kpić z danych wejściowych, i kpić z tego, co dzieje się wewnątrz rozszerzenia.
Uważam, że użycie rozszerzenia jest dodaniem kodu bezpośrednio do metody. Oznaczało to, że musiałem kpić z tego, co dzieje się wewnątrz rozszerzenia, a nie samo rozszerzenie.
źródło
Możesz mockować interfejs testowy, który dziedziczy po rzeczywistym i ma element członkowski z tym samym podpisem, co metoda rozszerzenia.
Następnie możesz mockować interfejs testowy, dodać rzeczywisty do makiety i wywołać metodę testową w konfiguracji.
Twoja implementacja makiety może następnie wywołać dowolną metodę lub po prostu sprawdzić, czy wywoływana jest metoda:
Dzięki rozwiązaniu Håvard S w tym poście za implementację makiety obsługującej dwa interfejsy. Kiedy już go znalazłem, dostosowanie go za pomocą interfejsu testowego i metody statycznej było jak spacer po torcie.
źródło
SomeNotAnExtensionMethod
iSomeNotAnExtensionMethod
? Mam teraz pomysł, jak utworzyć podpis metody rozszerzającej w interfejsie ...iReal
parametr doSomeExtensionMethod
w przypadkuITest
? Jeśli przekażesz go jako pierwszy parametr, to w jaki sposób skonfigurujesz?Setup( x=> x.SomeExtensionMethod(x, ...)
spowoduje to wyjątek w czasie wykonywania.object _mockCache = whatever
... `Setup (x => x.SomeExtensionMethod (...) .. Callback (() => możesz dostęp _mockCache tutaj);)Możesz łatwo mockować metodę rozszerzenia za pomocą JustMock . API jest tym samym, co mockowanie zwykłej metody. Rozważ następujące
Aby zorganizować i zweryfikować tę metodę, użyj następujących:
Tutaj jest również link do dokumentacji: Mockowanie metod rozszerzeń
źródło
Lubię używać opakowania (wzorca adaptera) podczas zawijania samego obiektu. Nie jestem pewien, czy użyłbym tego do zawijania metody rozszerzenia, która nie jest częścią obiektu.
Używam wewnętrznej właściwości Lazy Injectable typu Action, Func, Predicate lub delegate i pozwalam na wstrzyknięcie (zamianę) metody podczas testu jednostkowego.
Następnie wywołujesz Func zamiast rzeczywistej metody.
Aby uzyskać pełniejszy przykład, odwiedź http://www.rhyous.com/2016/08/11/unit-testing-calls-to-complex-extension-methods/
źródło
Więc jeśli używasz Moq i chcesz mockować wynik metody Extension, możesz użyć
SetupReturnsDefault<ReturnTypeOfExtensionMethod>(new ConcreteInstanceToReturn())
na wystąpieniu klasy pozorowanej, która ma metodę rozszerzenia, którą próbujesz mockować.Nie jest doskonały, ale do celów testów jednostkowych działa dobrze.
źródło