Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> PHPUnit, metoda prywatna i mock
irmidjusz
post
Post #1





Grupa: Zarejestrowani
Postów: 279
Pomógł: 60
Dołączył: 25.02.2012

Ostrzeżenie: (0%)
-----


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 (IMG:style_emoticons/default/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?

Ten post edytował irmidjusz 10.09.2012, 22:10:42
Go to the top of the page
+Quote Post
melkorm
post
Post #2





Grupa: Zarejestrowani
Postów: 1 366
Pomógł: 261
Dołączył: 23.09.2008
Skąd: Bydgoszcz

Ostrzeżenie: (0%)
-----


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 (IMG:style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
irmidjusz
post
Post #3





Grupa: Zarejestrowani
Postów: 279
Pomógł: 60
Dołączył: 25.02.2012

Ostrzeżenie: (0%)
-----


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ę (IMG:style_emoticons/default/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 (IMG:style_emoticons/default/smile.gif)

Ten post edytował irmidjusz 11.09.2012, 23:03:02
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 4.10.2025 - 22:01