wtorek, 27 grudnia 2011

Sky używa Grails

Grails nie jest niestety zbyt popularną technologią (sam myślę o tym, aby przerzucić się na inne twory z powodu ograniczonego rynku pracy), jednakże duże serwisy wykorzystują ją z powodzeniem. Przykładem tego jest sky.com, brytyjski gigant telewizyjny.

Artykuł opisujący przejście Sky.com na Grails

poniedziałek, 5 grudnia 2011

Testowanie kontrolerów Grails 2.0

Grailsy 2.0 (wydano już wersję RC3, więc finalna już bardzo niedługo) wprowadzają nową jakość do testowania. Porzucono całkowicie ideę (i słusznie) rozszerzenia klas dziedziczących po GrailsUnitTestCase i zastosowano tzw. mechanizm Mixins. Jest to jedna z fajnych właściwości języka Groovy, umożliwiająca dodawanie metod do klasy w runtime, więcej o niej tutaj.

Przejdźmy jednak do meritum. Poniższy kod prezentuje klasę testową kontrolera.

@TestMixin(DomainClassUnitTestMixin)
@TestFor(IndexController)
class IndexTests {

  def position

  @Before
  void setUp() {
    mockDomain(BusinessType)
    new BusinessType(name: "otherType.name").save()
  }

  @Test
  void shouldReturnLocatedPosition() {
      assert controller.index().position == position
  }
}

Dla osób, które pisały w Grails w wersji 1.x niektóre elementy wydadzą się znajome, a mianowicie metody mockDomain oraz obiekt controller. Jednakże tutaj uzyskujemy je dzięki adnotacjom @TestMixin oraz @TestFor.

TestFor jest standardową adnotacją, gdy chcemy testować, któreś z elementów MVC w Grails 2.0. Automatycznie rozpozna on typ klasy (Controller, Domain...) oraz wstrzyknie odpowiednie metody. Dla testów kontrolerów są to między innymi obiekt controller oraz obiekt response. Więcej o nich jednak w dokumentacji.

Druga adnotacja @TestMixin służy do łączenia testów różnych elementów MVC. W podanym przykładzie jako argument podałem DomainClassUnitTestMixin, co umożliwia mi wykorzystanie metody mockDomain, która to działa analogicznie z metodą mockDomain w GrailsUnitTestCase znaną z wersji 1.x.

Gdy chcemy testować z użyciem klas Domain, możemy także posłużyć się adnotacją @Mock([BusinessType]), która to automatycznie wykona metodę mockDomain (w tym przypadku nie musimy już korzystać z @TestMixin).

piątek, 2 grudnia 2011

Mockowanie konstruktorów

Gmock oferuje także bardzo przydatną funkcję mockowania konstruktorów. Jest to, co prawda pewnego rodzaju zły design, jeśli trzeba wykorzystać tą funkcjonalność, jednak jako że Groovy jest językiem dynamicznym i nie lubimy kodować niepotrzebnych fabryk, to taka funkcjonalność może być z powodzeniem wykorzystana. Dla przykładu podam kawałek kodu nad którym dzisiaj siedziałem. Musiałem skorzystać z generatora losowego, jednakże zależy mi w tym wypadku na wielowątkowości, więc musi być on tworzony dla każdego obiektu. Nie widzę sensu w tym przypadku, na tworzenie dodatkowej klasy fabryki dla typowego obiektu Java, więc zdecydowałem się na skorzystanie z mockowania konstruktora (kodu z wykorzystaniem generatora losowego z oczywistych względów nie można testować bez obiektów pozornych).
@Test
void shouldReturnDiscount2() {
  def mockRandom = mock(Random, constructor(anything()))
  mockRandom.nextInt(3).returns(2)
  play {returnValue = sut.getRandomActiveDiscount()}
}

I tak ten mały kawałek kodu mi to umożliwił. W tym przypadku mockuję konstruktor klasy Random, do którego przekazywany jest jakikolwiek parametr. Konstruktor ten zwróci mi obiekt mockRandom, na którym mogę wykonywać dalsze potrzebne mi operacje.