2015-08-13 19 views
9

È possibile simulare una proprietà protetta con PHP Mockery?È possibile simulare proprietà e metodi protetti

Ho ottenuto una classe con un metodo, la chiamerò `a, che fa un po 'di magia su un array che viene recuperato da una proprietà protetta dalla stessa classe.

La proprietà protetta viene riempita con un altro metodo b, nella stessa classe.

Vorrei testare il metodo a prendendo in giro la proprietà protetta in modo da non dover prima il metodo di classe b.

Quindi è possibile? In caso contrario, dovrei refactoring il mio codice? Oppure ci sono altri modi (considerando le migliori pratiche).

+2

prova utilizzando la riflessione – ArtisticPhoenix

+0

ho fatto (ovviamente) google e questa è stata davvero la prima cosa che è venuta fuori. Ma si sente un po 'di "hackery". Mi chiedo anche come posso mescolare questo con un parziale finto. – Ilyes512

+1

Se si ritiene che l'hackery si rifletta sul codice. Non sono del tutto sicuro di cosa vuoi fare, ma la riflessione è generalmente il modo di leggere dinamicamente le proprietà della classe quando non sai cosa sono. – ArtisticPhoenix

risposta

17

È possibile simulare metodi protetti, ma come alcune persone hanno sottolineato si potrebbe voler refactoring il codice se si sente la necessità di deridere questi metodi.

Se si vuole prendere in giro metodi protetti si può fare questo, secondo l'esempio di seguito:

$myMock = Mockery::mock('myClass')->shouldAllowMockingProtectedMethods(); 

Usando questo deridere è poi possibile prendere in giro metodi protetti nello stesso modo come si farebbe beffe metodi pubblici.

1

A volte il tuo codice va bene e tu pensi che non ci sia ragione di cambiare il tuo codice per facilitare i test (che è una buona ragione secondo me), quello che faccio è usare la riflessione all'interno del mio oggetto, puoi anche avere un metodo helper come questo:

class MockingHelpers 
{ 
    public static function mockProperty($object, string $propertyName, $value) 
    { 
     $reflectionClass = new \ReflectionClass($object); 

     $property = $reflectionClass->getProperty($propertyName); 
     $property->setAccessible(true); 
     $property->setValue($object, $value); 
     $property->setAccessible(false); 
    } 
} 

Nota l'accessibile è applicato solo nel contesto di riflessione, quindi nessun danno è fatto.

Non è la soluzione perfetta, a volte potresti avere un problema nel codice, ma questo potrebbe aiutarti!