Nie musimy chyba nikogo przekonywać, że podstawą bezpieczeństwa każdej aplikacji jest dokładna walidacja danych wprowadzanych przez użytkownika. Proces ten powinien być wykonywany nie tylko po stronie przeglądarki (klienta), ale i po stronie serwera.

Wykorzystywany przez nas framework Symfony2, oprócz udostępniania kilkudziesięciu podstawowych walidatorów, pozwala w prosty sposób tworzyć własne. W tym artykule nie będziemy jednak poruszać tematu ich pisania – na ten temat znajdziecie w sieci sporo informacji.

Tym razem chcielibyśmy skupić się na temacie testowania ich za pomocą frameworka PHPUnit.

Twórcy Symfony postanowili uprościć nam życie i stworzyli klasę AbstractConstraintValidatorTest będącą nakładką na PHPUnit_Framework_TestCase. Pozwala ona w przyjemny i bardzo czytelny sposób tworzyć testy dla obiektów ConstraintValidator.

Dla zilustrowania użyjemy przykładowego walidatora SecurePasswordValidator sprawdzającego czy hasło jest bezpieczne:

Jak widać, by hasło pozytywnie przeszło walidację musi mieć:

  • co najmniej 8 znaków
  • co najmniej dwie duże litery
  • co najmniej jeden znak specjalny
  • co najmniej 2 cyfry

Przejdźmy do testów jednostkowych. Wspomniana klasa AbstractConstraintValidatorTest posiada jedną metodę abstrakcyjną, którą musimy zaimplementować. Jest nią createValidator, zwracająca w naszym przypadku obiekt testowanego przez nas walidatora SecurePasswordValidator.

Nasz pierwszy test będzie sprawdzał, czy w razie przekazania bezpiecznego hasła walidator nie zgłosi żadnego błędu. Służy do tego specjalna asercja assertNoViolation:

Drugi test to przypadek przekazania niebezpiecznego hasła. Tutaj z pomocą przychodzi nam metoda buildViolation, sprawdzająca czy walidator wykrył błąd. Jako argument przyjmuje ona komunikat błędu jaki “rzuca” walidator, zwraca natomiast obiekt ConstraintViolationAssertion pozwalający budować szczegółową asercję.

Tym sposobem możemy dodatkowo sprawdzić czy ustawiony jest parametr komunikatu (wykorzystywane do translacji), a także czy błąd zgłaszany jest dla odpowiedniej ścieżki pola (przydatne przy formularzach).

Na koniec musimy wspomnieć o pewnej niedogodności – AbstractConstraintValidatorTest wykorzystuje do tworzenia mocków (m.in. translatora) metodę getMock, która od PHPUnit 5.4.0 jest już deprecated. Na szczęście niebawem możemy spodziewać się poprawki.

Poniżej pełen kod testów jednostkowych: