środa, 16 listopada 2011

Partial Mock

Partial mock jest to sposób na "udawanie" tylko niektórych metod z obiektu. W ten sposób, gdy chcemy aby obiekt działał normalnie, a chcemy w jakimś celu skorzystać z funkcjonalności frameworka do obiektów pozornych możemy to uczynić.

W Grailsach jest to przydatne narzędzie, ponieważ często używane są dynamicznie wstrzykiwane metody (np. do kontrolerów) do których nie mamy dostępu w środowisku testowym, a z których korzysta kod.

Poniższy przykład demonstruje użycie partial mock we frameworku gmock:

def controller = new SomeController()
def mockRequest = mock()
mockController.request.returns(mockRequest)

Dla instancji controller podmieniamy w tym przypadku właściwość request na nasz mockRequest. Jak widać składnia partial mock jest identyczna jak składnia przy typowych obiektach pozornych, więc skorzystanie z tej techniki będzie wyjątkowo łatwe.

niedziela, 13 listopada 2011

Gmock

W TDD istnieją dwa podejścia do testów interakcji:
  • klasyczne, gdzie wykorzystuje się prawdziwe obiekty, jeśli można
  • z wykorzystaniem obiektów pozornych (Mock objects) 
Drugie podejście jest bliższe idei testów jednostkowych, ponieważ pozwala przetestować kod w prawdziwej izolacji od innych obiektów. Dzięki dobremu wykorzystaniu obiektów pozornych można łatwo sprawdzić interakcje między obiektami, nawet jeśli nie zwracają one żadnych wartości.

Takie podejście w projektach opartych o architekturę MVC, do których oczywiście zaliczają się Grailsy, jest bardzo przydatne m.in. w kontrolerach, które zwykle operują na obiektach klas domenowych czy też serwisów. Dzięki zastosowaniu mocków możemy łatwo sprawdzić czy kontroler wykonuje powierzone mu zadania i nie jesteśmy uzależnieni od faktycznej implementacji innych warstw.

Dzięki dynamiczności języka Groovy, obiekty pozorne można tworzyć bez użycia wyspecjalizowanych frameworków, jednakże jest to dość niewygodne. Powstało kilka projektów mających na celu uczynienie tego łatwiejszym. Jeden z nich (MockFor) jest zintegrowany w Groovy on Grails, jednakże mi osobiście nie podpasował. Wobec czego polecam Gmock, z którego sam także korzystam.

Instalacja Gmock w projekcie Grails nie jest skomplikowana, jednakże aktualnie nie istnieje żaden plugin, który bo to jeszcze ułatwiał. Skorzystamy, więc z Mavena i pliku conf/BuildConfig.groovy. W sekcji odpowiadającej za dependencies dopisujemy:
test 'org.gmock:gmock:0.8.1'
Aby wykorzystać Gmock w swoim teście możemy zastosować jedną z 3 metod:
  • dziedziczyć po klasie GMockTestCase (to jest opisane w dokumentacji Gmock, jednakże to podejście nie jest najlepsze z różnych przyczyn, więc nie będę go szerzej opisywał)
  • dodać adnotację @WithGMock do klasy testu (to jest najfajniejsze rozwiązanie, jednakże w aktualnej wersji nie działa z Grails 2.0)
  • użyć obiektu typu GMockController() 
We wszystkich poniższych przykładach zakładam, że istnieje już obiekt typu GMockController o nazwie gmock (jeśli ktoś korzysta z metody 1 lub 2, to we wszelkich wołaniach można go pominąć. Czyli zamiast gmock.metoda() piszemy metoda()).

 Tworzenie obiektów pozornych jest bardzo łatwe i opiera się na prostym DSL stworzonym w tym celu.

I tak dla klasy SpringSecurityService tworzymy go w następujący sposób:
def springSecurityMock = gmock.mock(SpringSecurityService)
W ten sposób mamy utworzony obiekt pozorny, jednakże jeszcze bez żadnych metod, czy też sprawdzania warunków. Aby dodać warunki skorzystamy z poniższego kodu:

springSecurityMock.encodePassword("password").returns("asd").times(1)
 Powyższy kod można rozbić na kilka członów:
  • springSecurityMock.encodePassword("password") - jest to zdefiniowanie metody encodePassword, która spodziewa się podanego parametru
  • returns("asd") - zdefiniowane wartości zwracanej dla metody z poprzedniego kroku
  • .times(1) - nasze założenie testowe
Powyższy kod można wobec tego przeczytać jako: spodziewaj się jednokrotnego wywołania metody encodePassword z parametrem "password" i zwróc "asd".

Tak przygotowane założenie sprawdzamy za pomocą metody play:
gmock.play { sut.someMethodThatCallsEncodePassword() }

 Poniżej prezentuję całą metodę testową z wykorzystaniem Gmock:
@Test
void shouldCallEncodePassowrd() {
  def gmock = new GMockController()
  sut.springSecurity = gmock.mock(SpringSecurityService)
  sut.springSecurity.
    encodePassword("password").returns("asd").times(1)   gmock.play { sut.someMethodThatCallsEncodePassword() } }
Powyższy kod wykona się poprawnie, gdy metoda  someMethodThatCallsEncodePassword faktycznie zawoła metodę encodePassword z parametrem "password".

Gmock jest bardzo ciekawą biblioteką, ponieważ potrafi podmieniać także metody statyczne, bądź też metody na żywych obiektach (tzw. partial mock), jednakże o tym w następnych postach.

sobota, 12 listopada 2011

Grails 2.0

W związku z niedługim wydaniem nowej wersji Grails postanowiłem zacząć pisać bloga o tej technologii. Postaram się tutaj opisywać raczej ciekawostki i nowości niż samouczek dla początkujących, ponieważ takich trochę w internecie jest, ale znajdą się tutaj też informacje na różnym stopniu zaawansowania. Na początek pójdzie testowanie z użyciem GMock. Pierwszy wpis już wkrótce.