Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHPUnit] Nadpisanie metody statycznej
kapslokk
post 8.06.2016, 13:09:26
Post #1





Grupa: Zarejestrowani
Postów: 965
Pomógł: 285
Dołączył: 19.06.2015
Skąd: Warszawa

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


Cześć,
próbuje napisać test, dla klasy, która korzysta z innej. Przykład:

  1. class A{
  2. public static function get(){
  3. return 1;
  4. }
  5. }
  6.  
  7. class B{
  8. private $a;
  9. public function __construct($a){
  10. $this->a = $a;
  11. }
  12. public function doSomething(){
  13. return $this->a->get();
  14. }
  15. }

No i jak próbuje zrobić mock metody get i jest tam "static", to po prostu pomija ten test. Jeżeli usunę "static" - wszystko działa ok.

Nie pytajcie po co ten static tam w ogole jest - nie moja wina, grzebe w starym kodzie, nie mogę go usunąć.
Używam PHPUnit 5.4.2


Go to the top of the page
+Quote Post
LowiczakPL
post 8.06.2016, 21:51:37
Post #2





Grupa: Zarejestrowani
Postów: 531
Pomógł: 55
Dołączył: 3.01.2016
Skąd: Łowicz

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


Coś mało dałeś jak na mocka ale czy nie tak to powinno wyglądać w Twoim przypadku

  1. class A
  2. {
  3. public static function doSomething()
  4. {
  5. return static::get();
  6. }
  7.  
  8. public static function get()
  9. {
  10. return '1';
  11. }
  12. }
  13.  
  14. class ATest extends PHPUnit_Framework_TestCase
  15. {
  16. public function testDoSomething()
  17. {
  18. $class = $this->getMockClass(
  19. 'A',
  20. array('get')
  21. );
  22.  
  23. $class::staticExpects($this->any())
  24. ->method('get')
  25. ->will($this->returnValue('1'));
  26.  
  27. $this->assertEquals(
  28. '1',
  29. $class::doSomething()
  30. );
  31. }
  32. }




--------------------
Szukam zleceń Symfony, Laravel, Back-End, Front-End, PHP, MySQL ...
Go to the top of the page
+Quote Post
kapslokk
post 9.06.2016, 07:12:35
Post #3





Grupa: Zarejestrowani
Postów: 965
Pomógł: 285
Dołączył: 19.06.2015
Skąd: Warszawa

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


Dałem przykład klas, do których chce zrobić mocka, samego mocka nie dawałem, bo po prostu nie działał. Co do ::staticExpects to w mojej wersji PHPUnit nie ma tej metody.

Ten post edytował kapslokk 9.06.2016, 07:15:12
Go to the top of the page
+Quote Post
LowiczakPL
post 9.06.2016, 17:29:29
Post #4





Grupa: Zarejestrowani
Postów: 531
Pomógł: 55
Dołączył: 3.01.2016
Skąd: Łowicz

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


To wklej swój kod łatwiej będzie to ogarnąć.


--------------------
Szukam zleceń Symfony, Laravel, Back-End, Front-End, PHP, MySQL ...
Go to the top of the page
+Quote Post
Crozin
post 9.06.2016, 19:38:39
Post #5





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


1. Wiem, że PHP pozwala na pewne głupoty, ale dlaczego wywołujesz metody statyczne jak metody obiektu?
2. Tutaj mamy koronny przykład dlaczego w zdecydowanej większości przypadków użycie statycznych metod jest złe i niepożądane. Metody statyczne są praktycznie niemożliwe do testowania bez "hacków" w postaci np. dynamicznej podmiany byte-code'u.
3. Opisz może dokładniej swój przypadek (albo podaj wręcz faktyczny kod) - być może wcale nie ma potrzeby do tworzenia mocka.
Go to the top of the page
+Quote Post
kapslokk
post 9.06.2016, 20:19:50
Post #6





Grupa: Zarejestrowani
Postów: 965
Pomógł: 285
Dołączył: 19.06.2015
Skąd: Warszawa

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


1. Nie pytaj, bo po prostu nie potrafię odpowiedzieć na to pytanie. Ktoś przede mną w firmie zrobił głupotę i teraz z tego korzystam,
2. Wiem, gdybym robił to od początku, zrobił bym to inaczej.
3. Ogólnie chodzi o to, że nowe funkcjonalności w serwisie piszemy obiektowo, natomiast znaczna większość jest napisana strukturalnie. PM nie pozwolił nam się od tego odciąć (czemu? nie mam pojęcia, nie dało się mu wytłumaczyć), dlatego ktoś kiedyś zrobił klasę, która służy tylko do tego, żeby wyciągać zmienne globalne przez nią - jest napisana z nadzieją, że kiedyś uda nam się odciąć od tych globali, niestety ten ktoś wsadził tam static i zamiast wstrzykiwać odpowiednie zależności do innych klas używał w nich Klasa::get('costam'). W tym co ja pisałem, używając tej klasy, wstrzykiwałem jej obiekt jako zależność, no ale nie mogę tak po prostu usunąć tego "static" - bo inne funkcjonalności przestaną działać. Stąd cały problem.
Czyli ogólnie to static jest nie do ruszenia - bo tak biggrin.gif
Mam zatem np klasę do pobierania jakiegoś tam linku która w metodzie get() ma np. $this->globals->get('pageUrl').'/'.$this->pobierzTamJakisLink(). Chciałem ją przetestować mockując $this->globals->get() tak, żeby zawsze zwracał pusty ciąg znaków.

@LowiczakPL
A:
  1. <?php
  2.  
  3. namespace Example;
  4.  
  5.  
  6. class A
  7. {
  8. public function doSomething()
  9. {
  10. return ('A->doSomething');
  11. }
  12. }


B:
  1. <?php
  2.  
  3. namespace Example;
  4.  
  5.  
  6. class B
  7. {
  8. public static function doSomething()
  9. {
  10. return ('B->doSomething');
  11. }
  12. }



  1. public function testExample(){
  2.  
  3. $a = $this->getMockBuilder('Example\A')->setMethods(['doSomething'])->getMock();
  4. $a->expects($this->any())->method('doSomething')->will($this->returnValue('AMock->doSomething'));
  5.  
  6. $b = $this->getMockBuilder('Example\B')->setMethods(['doSomething'])->getMock();
  7. $b->expects($this->any())->method('doSomething')->will($this->returnValue('BMock->doSomething'));
  8.  
  9. var_dump($a->doSomething());
  10. var_dump($b->doSomething());
  11. }

Zwraca:
PHPUnit 5.4.4 by Sebastian Bergmann and contributors.

string(18) "AMock->doSomething"


Time: 65 ms, Memory: 4.00MB


WARNINGS!
Tests: 1, Assertions: 0, Warnings: 1.
Go to the top of the page
+Quote Post
Crozin
post 10.06.2016, 07:36:12
Post #7





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


Możesz spróbować wyrzucić odwołania do nieszczęsnej klasy statycznej do pośredniczącego obiektu.
  1. class Config {
  2. public static get(...);
  3. public static set(...);
  4. }
  5.  
  6. interface ConfigProviderInterface {
  7. public get();
  8. public set();
  9. }
  10.  
  11. // implementacja wykorzystywana w normalnym kodzie
  12. class StaticConfigProvider implements ConfigProviderInterface {
  13. public get() {
  14. return Config::get(...);
  15. }
  16.  
  17. public set() {
  18. Config::set(...);
  19. }
  20. }
  21.  
  22. // implementacja wykorzystywana w testach
  23. class ArrayConfigProvider implements ConfigProviderInterface {
  24. private $config;
  25.  
  26. public get() {
  27. return $this->config[...];
  28. }
  29.  
  30. public set() {
  31. $this->config[...] = ...;
  32. }
  33. }
  34.  
  35. class MyClass {
  36. private $config;
  37.  
  38. public __construct(ConfigProviderInterface $config) {
  39. $this->config = $config;
  40. }
  41.  
  42. public doSth() {
  43. return 'abc' . $this->config->get(..);
  44. }
  45. }
  46.  
  47. // ---- TESY:
  48.  
  49. $config = new ArrayConfigProvider([....]);
  50. $class = new MyClass($class);
  51.  
  52. $this->assertEquals('abc123', $class->doSth());
Go to the top of the page
+Quote Post
kapslokk
post 10.06.2016, 07:48:27
Post #8





Grupa: Zarejestrowani
Postów: 965
Pomógł: 285
Dołączył: 19.06.2015
Skąd: Warszawa

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


To ma sens smile.gif będę próbował w wolnej chwili smile.gif Dzięki smile.gif

Ten post edytował kapslokk 10.06.2016, 07:48:36
Go to the top of the page
+Quote Post

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

 



RSS Wersja Lo-Fi Aktualny czas: 27.04.2024 - 05:31