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:

$client = $this->getMock('GearmanClient', array('doBackground'));
$client
  ->expects($this->once())
  ->method('doBackground')
  ->with(
    self::equalTo('methodname'),
    self::logicalAnd(
      self::stringContains('"kulcs1":"' . $v1 . '"'),
      self::matchesRegularExpression('/"kulcs2":"[^,]+",/')
    )
  );
 
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:

$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.

class PHPUnit_Framework_MockObject_Stub_ReturnCallback implements PHPUnit_Framework_MockObject_Stub
{
    protected $callback;
    protected $extra_arguments;

    public function __construct($callback, $extra_arguments)
    {
        $this->callback = $callback;
        $this->extra_arguments = $extra_arguments;
    }

    public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        return call_user_func_array($this->callback, array_merge($invocation->parameters, $this->extra_arguments));
    }
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).

    protected function returnCallback($callback, $extra_arguments = array())
    {
        return new PHPUnit_Framework_MockObject_Stub_ReturnCallback($callback, $extra_arguments);
    }
És végülis ennyi, de nem tudom, megéri-e.