ugrás a tartalomhoz

PHPUnit mock paraméter decoding

Protezis · 2010. Szep. 20. (H), 16.42
Üdv!

PHPUnit-ban egy mock objektumnál a paraméter vizsgálatnál elakadtam, mivel base64 enkódolva van, a mock with() metódusában pedig ellenőrzés előtt dekódolni kellene, azonban nem tudom, ezt hogy lehet elérni.

Tehát a paramétert így adom át: base64_encode(json_encode($param))

base64_encode nélkül az alábbi kód tökéletesen működik:
  1. $client = $this->getMock('GearmanClient'array('doBackground'));  
  2. $client  
  3.   ->expects($this->once())  
  4.   ->method('doBackground')  
  5.   ->with(  
  6.     self::equalTo('methodname'),  
  7.     self::logicalAnd(  
  8.       self::stringContains('"kulcs1":"' . $v1 . '"'),  
  9.       self::matchesRegularExpression('/"kulcs2":"[^,]+",/')  
  10.     )  
  11.   );  
 
1

Hááát

gphilip · 2010. Szep. 20. (H), 17.21
Sajnos a PHPUnit nem támogat callbacket vagy ilyesmit Constraintben. 2 megoldás van, az egyik fájdalmas a máik csúnya :)

Az első, hogy írsz egy saját Constraint class-t a PHPUnit-hoz, ami az igényeidhez igazodik. Nyiss meg egy Constraint class-t és bizonyosodj meg róla, hogy ezt nem akarod csinálni :)

A második valami ilyesmi:
  1. $client->expects( $this->once() )->method( 'doBackground' )->will( $this->returnCallback( array$this'callback' ) );  
Majd létrehozod a callback metódust a teszt osztályodban, ami a doBackground eredeti argumentumaival lesz meghívva. Ezután a callback metódus szépen eldönti, hogy minden oké-e, és ha igen, visszatér akármivel, ha nem, meghívja a self::failt()-t.

Ez az élmélet, kívnácsi vagyok, beválik-e gyakorlatban, még sosem csináltam így :)
2

Köszi, holnap reggel ezzel

Protezis · 2010. Szep. 20. (H), 18.04
Köszi, holnap reggel ezzel kezdek :)
3

Működik :) Egyetlen

Protezis · 2010. Szep. 21. (K), 10.15
Működik :)
Egyetlen szépséghiba, hogy a callback metódusban fel szeretnék használni néhány változót, amiket a testcase-ben definiáltam. A returnCallback() azonban ezeket nem passzolja tovább, úgyhogy kénytelen voltam kirakni member változóba a tesztelendő értékeket (és azokat így már elérem a callback-ben).

Erre esetleg van jobb ötleted?

Egyébként teljesen igazad van, a PHPUnit oldalán pontosan ott van a példa, csak ott a visszatérési érték ellenőrzése végett használja ezt a megoldást, míg én az argumentumokat vizsgálom.
4

Extending

gphilip · 2010. Szep. 21. (K), 12.13
Hali,

Sajnos a változók "megtartására" nincs túl jó módszer, a tulajdonságokba mentés kielégítő megoldás.

Opcinálisan kiterjesztheted a PHPUnitot, ami egyébként nem annyira javasolt, ha mondjuk a jövőben frissítenéd. Esetleg csinálj egy forkot róla és kérj egy merge request-et, szerintem ez a változás beleillik a képbe.

http://github.com/sebastianbergmann/phpunit/

Szóval a lényeg:

Megkeresed a PHPUnit_Framework_MockObject_Stub osztályt, és hozzáadsz egy új argumentumot a konstruktorhoz, amit később a callback hívásánál használsz az eredeti argumentumokkal együtt.
  1. class PHPUnit_Framework_MockObject_Stub_ReturnCallback implements PHPUnit_Framework_MockObject_Stub  
  2. {  
  3.     protected $callback;  
  4.     protected $extra_arguments;  
  5.   
  6.     public function __construct($callback$extra_arguments)  
  7.     {  
  8.         $this->callback = $callback;  
  9.         $this->extra_arguments = $extra_arguments;  
  10.     }  
  11.   
  12.     public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation)  
  13.     {  
  14.         return call_user_func_array($this->callback, array_merge($invocation->parameters, $this->extra_arguments));  
  15.     }  
A TestCase osztályban megkeresed a returnCallback metódust, és hozzáadsz egy extra opcionális argumentumot (amit a fent módosított konstruktorban használsz majd).
  1. protected function returnCallback($callback$extra_arguments = array())  
  2. {  
  3.     return new PHPUnit_Framework_MockObject_Stub_ReturnCallback($callback$extra_arguments);  
  4. }  
És végülis ennyi, de nem tudom, megéri-e.