Mocki które nie są mockami, wasze zdanie (Ankieta)

0

Siemka, mam sobie czasem serwisy w aplikacji które ciągną dane o userach, główne dwie to jest ciągnięcie username'a po id, i id po usernamie.

Więc w testach wszędzie jest

when(userRepository.findUsernameById(2)).thenReturn("john doe");
when(userRepository.findUserIdByUsername("john doe")).thenReturn(2);

Wiecie, bo repository wymusza kontrakt. Jest jeden user o id=2 i jeden o username'ie "john doe". Wiec to się musi wymusić nawzajem.

Np zrobienie czegoś takiego nie ma sensu:

when(userRepository.findUsernameById(2)).thenReturn("john doe");
when(userRepository.findUserIdByUsername("john doe")).thenReturn(4); // złe id usera, inne niż kontrakt wymusza

I się zastanawiam, czy do testów nie zrobić testowej implementacji user repository, który po prostu brałby te dane z bimapy.

userRepository = new TestUserRepository(singletonMap(2, "john doe"));

Zamiast mockitowych when().thenReturn(). To byłoby bardziej deklaratywne podejście, plus nie można by tego skopać, co myślicie?

5

Ja robię implementację opartą na mapie i żyję. IHMO po to wyciąga się interfejs repozytorium żeby móc robić inne implementacje. Także testowe

1
KamilAdam napisał(a):

IHMO po to wyciąga się interfejs repozytorium żeby móc robić inne implementacje. Także testowe

Ależ mock jest właśnie inną implementacją. :)

2

Ja robie tylko tą implementacje na hashmapie. Zapisywanie w bazie danych jest takie 1999.

2

@TomRiddle: have you heard about our lord and saviour in-memory-db? ;) Może zamiast mockować repozytorium odpalisz h2 i zostawisz w kodzie twoje normalne repozytorium i podmienisz tylko bazę na taką w której na czas testu wrzucisz odpowiednie dane?
Jeśli chodzi o "deklaratywne podejście" to polecam napisać sobie DSL do testów, żeby w ogóle takie rzeczy ukryć przed piszącym/czytającym testy. Ty sobie w teście zrobisz testSetup.withUser(x,y).withCośtam()... a że pod spodem będzie jakieś mockito albo wrzucanie czegoś do h2 albo do mapy w twoim TestRepository to są szczegóły i pisząc test w ogóle nie powinieneś się tym przejmować.

shameless plug: https://github.com/Pharisaeus/almost-s3

0
Shalom napisał(a):

@TomRiddle: have you heard about our lord and saviour in-memory-db? ;) Może zamiast mockować repozytorium odpalisz h2 i zostawisz w kodzie twoje normalne repozytorium i podmienisz tylko bazę na taką w której na czas testu wrzucisz odpowiednie dane?

Pomysł fajny, dzięki, na pewno skorzystam kiedy będę pisał coś z bazą prywatnie next time.

@Shalom Nie mów nikomu, ale tak na prawdę w moim przykładzie nie było UserRepository żadnego. To była przykrywka, żeby nikt nie mógł wyśledzić mojego oryginalnego problemu.

Prawdziwa klasa robiła fetche z pliku i z propertiesów na raz, i miała tylko dwie metody, mapowanie A na B, i B na A, które zawsze, by design miały być 1:1. Oczywiście ludzie używali mockito, i czasem w when()ach się walnęli i mockito już nie wymuszało kontraktu A 1:1 B. Mockowanie tych popertiesów i plików to byłaby rzeź (i jeszcze łatwiej byłoby się walnąć), nie ma żadnego gotowego rozwiązania, a framework z którego klasa korzysta też nowy nie jest.

Dodałem TestKlasa (pierwsza odpowiedź w ankiecie), która bierze te dane z BiMap<> z guavy, i zostałem opierdolony czemu odchodzę od konwencji :D Więć pomyślałem żę poszukam na 4programmers walidacji mojego pomysłu żeby nie popaść w szaleństwo.8

2

@TomRiddle ja mimo wszystko pozwoliłbym na testowanie tego "repozytorium" właśnie szczególnie dlatego ze jest "dziwne"! Więc zrobiłbym sobie setup gdzie DSL testowy "generuje stan". Przecież to bez różnicy czy robi inserty do bazy, czy wrzuca coś do mapy czy tworzy jakieś pliki na dysku. Jasne że to trochę ból to napisać, ale potem przynajmniej faktycznie testujesz kod aplikacji a nie mocka.
A jak masz ładny DSL to w teście nadal jest tylko .withUser(...) i pisząc test nie obchodzi cię że pod spodem to robi jakiś hardkor, tworzy pliki i properties ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1