Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: PHPUnit, metoda prywatna i mock
Forum PHP.pl > Forum > PHP
irmidjusz
Testy jednostkowe w PHPUnit i PHP 5.3.
Mam następujące klasy (oczywiście to schemat z jedynie kluczowymi elementami kodu):

  1. class FirstClass {
  2. private function testedMethod($param){
  3. //ciezko pracujemy
  4. $value = $this->someMethod($param);
  5. //skladamy wynik na podstawie wartosci $value i zwracamy
  6. return $result;
  7. }
  8.  
  9. public function someMethod($param){
  10. //przygotowanie tablicy danych, wsrod ktorych znajduje sie wartosc pobrana z wywolania:
  11. $value = $this->getObject()->getValue();
  12. //... dalej przetwarzanie i:
  13. return $data;
  14. }
  15.  
  16. public function getObject(){
  17. //tra la la cos tam i w koncu
  18. return new SecondClass();
  19. }
  20. }
  21.  
  22. class SecondClass {
  23. public function getValue(){
  24. //call external service and return result
  25. return $result
  26. }
  27. }


Teraz chodzi o to, że chcę przetestować czy FirstClass::testedMethod zwraca poprawne dane, bo jest to metoda uzywana przez kilka metod publicznych klasy FirstClass i to w niej zawarta jest istotna funkcjonalnosc logiczna. Pozostale metody wywolujace testedMethod w zasadzie jedynie przetwarzaja i dekoruja wynik zwrocony z testedMethod().

Problem w tym, ze musze zamokować metodę SecondClass::getValue, bo w warunkach testowych zupelnie odpada jej uzycie: odwoluje sie do zewnetrznych zasobow niedostepnych w srodowisku testowym, jest zlozona, zwraca nieprzewidywalne wyniki itd. - wiadomo o co chodzi smile.gif
Wszystko bylo by proste, gdyby metoda FirstClass::testedMethod() byla publiczna - ale jest prywatna i chce, zeby taka pozostala.

Czy można w PHPUnit przetestować bezpośrednio testedMethod() dla różnych podanych parametrów z jednoczesnym mockiem na metodę SecondClass::getValue, która ma zwracać stałą wartość? Czy to jest w ogóle możliwe?

Wiem jak:
- testować metody prywatne/chronione (za pomocą refleksji) ale bez użycia mocka (w tym przypadku na SecondClass::getValue())
- jak testować publiczną metodę FirstClass::testedMethod() z mockowanym wywołaniem SecondClass::getValue().

Ale nie potrafię zrobić tego gdy testedMethod jest prywatna a muszę mieć zamockowane użycie SecondClass:getValue().

Da się? Jak?
melkorm
Testowanie prywatnych metod trochę mija się z celem, ponieważ tak na prawdę co powinieneś testować to interfejs jaki daje Tobie obiekt czyli metody publiczne, ale jeżeli na prawdę chcesz testować tę metodę prywatną to moim zdaniem najlepszy rozwiązaniem będzie stworzenie dodatkowej klasy (tylko na potrzeby testowania) która będzie rozszerzać FirstClass i dodać metodę publiczną która będzie metodą proxy dla testedMethod. Jest to trochę brudne rozwiązanie ale na tę chwilę nic innego nie przychodzi mi do głowy smile.gif
irmidjusz
Cytat(melkorm @ 11.09.2012, 10:30:08 ) *
Testowanie prywatnych metod trochę mija się z celem, ponieważ tak na prawdę co powinieneś testować to interfejs jaki daje Tobie obiekt czyli metody publiczne


Zgadzam się smile.gif Ale w drodze wyjątku tę prywatną metodę także chciałem przetestować ze względu na jej specyficzną rolę i zwracane dane.
Myślałem też o takim podejściu, jakie zaproponowałeś, znalazłem m.in. http://www.phpclasses.org/package/5659-PHP...te-members.html - może się komuś przyda.
Ale ostatecznie poradziłem sobie inaczej i w sumie poprawniej - wydzieliłem część kodu owej testedMethod do osobnej prywatnej metody i dało się przetestować wszystko na czym mi zależało. A przy okazji obie te metody są teraz czytelniejsze i prostsze, bo każda wykonuje oddzielne, specyficzne zadanie. Zasada jednej odpowiedzialności znowu okazała się słuszna smile.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.