Biorąc pod uwagę następujący interfejs:
public interface IFoo
{
bool Foo(string a, bool b = false);
}
Próba kpiny za pomocą Moq:
var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);
daje następujący błąd w czasie kompilacji:
Drzewo wyrażeń nie może zawierać wywołania ani wywołania używającego opcjonalnych argumentów
Zauważyłem, że powyższy problem został podniesiony jako ulepszenie na liście problemów Moq i wydaje się, że jest on przypisany do wydania 4.5 (jeśli tak jest).
Moje pytanie brzmi: co powinienem zrobić, biorąc pod uwagę, że powyższe nie zostanie naprawione w najbliższym czasie? Czy moje opcje są tylko po to, aby albo jawnie ustawić domyślną wartość opcjonalnego parametru za każdym razem, gdy go mockuję (który rodzaj pokonuje punkt określania jednego w pierwszej kolejności) lub utworzyć przeciążenie bez bool (tak jakbym zrobił przed C # 4)?
Czy może ktoś znalazł bardziej sprytny sposób na rozwiązanie tego problemu?
źródło
Odpowiedzi:
Uważam, że teraz jedynym wyborem jest jawne uwzględnienie
bool
parametru w konfiguracji dlaFoo
.Nie sądzę, żeby to przeczyło celowi określenia wartości domyślnej. Wartość domyślna to wygoda przy wywoływaniu kodu, ale myślę, że w testach powinieneś być wyraźny. Powiedzmy, że możesz pominąć określanie
bool
parametru. Co się stanie, jeśli w przyszłości ktoś zmieni domyślną wartośćb
natrue
? Doprowadzi to do niepowodzenia testów (i słusznie), ale będą one trudniejsze do naprawienia z powodu ukrytego założenia, jakimb
jestfalse
. Jawne określeniebool
parametru ma jeszcze jedną zaletę: poprawia czytelność testów. Ktoś je przeglądając szybko zorientuje się, że istnieje jednaFoo
funkcja, która przyjmuje dwa parametry. To przynajmniej moje 2 centy :)Jeśli chodzi o określanie go za każdym razem, gdy go mockujesz, nie powielaj kodu: utwórz i / lub zainicjuj makietę w funkcji, aby mieć tylko jeden punkt zmiany. Jeśli naprawdę chcesz, możesz pokonać pozorne niedociągnięcia Moqa, powielając
Foo
parametry w tej funkcji inicjalizacyjnej:źródło
if (!x) {} else {}
anty-wzór :)Właśnie dzisiaj napotkałem ten problem, Moq nie obsługuje tego przypadku użycia. Wydaje się więc, że zastąpienie metody byłoby wystarczające w tym przypadku.
Teraz obie metody są dostępne i ten przykład zadziała:
źródło
Korzystając z Moq w wersji 4.10.1 mogłem wykonać następujące czynności
Z interfejsem:
I Mock
Rozwiązuje wywołanie Foo z pierwszym parametrem w porządku
źródło