2012-11-14 11 views
9

Gibt es eine Möglichkeit, mit phpunit eine Scheinklasse im Gegensatz zu einem Scheinobjekt zu erstellen? Ich suche nach einer Möglichkeit, Abhängigkeitsinjektion durchzuführen, ohne jedes Objekt explizit übergeben zu müssen, mit dem eine Klasse im Konstruktor (oder wo auch immer) arbeiten muss. Etwas, das „true“ für alle diese Fälle zurück:Erstellen Sie eine Scheinklasse mit phpunit?

public function testAAAA() 
{ 
    $foo = $this->getMock('foo', array('bar')); 
    var_dump(class_exists('foo', false)); 
    var_dump(method_exists('foo', 'bar')); 
    var_dump(method_exists($foo, 'bar')); 
} 

Diese Drucke:

bool(true) 
bool(false) 
bool(true) 

darauf hinweist, dass, während er erfolgreich eine gefälschte ‚foo‘ Klasse erstellt haben es nicht binden, um eine ‚Bar 'Methode dazu.

Ich benutze phpunit 3.7.5.

Antwort

10

Ich vermute, dass Sie eigentlich gar nicht, dies zu tun möchten (wie Sie Konstrukteuren deaktivieren und so weiter mit PHPUnit mockbuilder finden the docs), aber vorausgesetzt, Sie wollen oder müssen, sollte dies den Trick:

Ich bin ehrlich gesagt nicht sicher über die Besonderheiten, warum Sie oben andere Namen (nonexistant und foo) angeben müssen, aber es scheint mit PHPUnits Verhalten zu tun, wenn die Klasse, die verspottet wird, noch nicht existiert, und nachdem setMockClassName eine Klasse generiert hat, die diese Klasse erweitert. Oder so. Es ist wahrscheinlich effektiv um einen Fehler/Edge-Case - das ist eine seltsame Verwendung der Bibliothek. Sie sollten das gleiche durch die getMock Funktion allein tun können, es ist nur hässlicher.

Nebenbei klingt es so, als ob Sie sich wahrscheinlich mit php's reflection capabilities vertraut machen sollten. Es ist nicht die stärkste Reflektionsbibliothek da draußen, aber es ist ziemlich nett. Ich habe es verwendet, um Metainformationen über erforderliche und optionale Felder für eine Klasse basierend auf ihren Konstruktorargumenten und Eigenschaften für eine "Modell" -Bibliothek zu generieren, wobei diese Metainformationen zum Generieren von Formularen verwendet werden, die die korrekten Wertetypen akzeptieren. Das heißt, generierte typisierte Formulare ohne Instanzen der Klasse, für die das Formular bestimmt ist, und ohne eine dumme Menge Code von Hand zu schreiben - es sind insgesamt etwa 100 Zeilen für das gesamte Feature. Offensichtlich weiß ich nicht, was du versuchst zu tun, aber aufgrund der kleinen Menge an Informationen in deinem Beitrag würde ich vermuten, dass es näher an dieser Art von Meta-Ding ist als nicht.

+0

Ich würde nicht sagen, dass ich das unbedingt tun möchte, aber es ist, was ich tun muss. Ich muss in der Lage sein, ein Mock-Objekt zu generieren, das auf Aufrufe innerhalb des Tests reagiert, ohne Zehntausende von Dateien zu ändern, um echte DI hinzuzufügen. Diese getMockBuilder-Methode bringt mich nahe, aber es sieht so aus, als würde phpunit schlechten Evaluierungscode erzeugen, wenn er mit einem namespaced Schein-Klassennamen aufgerufen wird (etwas, das ich benutze, das ich im ursprünglichen Post hätte erwähnen sollen). –

+0

fügen Sie einen Aufruf von 'class_alias' wie' class_alias ('foo', 'quux \ baz') 'nach dem' getMock() 'Aufruf hinzu, und testen Sie dann gegen' quux \ baz'. Nichtsdestotrotz denke ich, dass Sie im Grunde an dem Punkt sind, an dem Sie möglicherweise PHPUnit patchen möchten oder die Fähigkeit von ReflectionClass und ReflectionObject verwenden, Methoden zu einem Objekt oder einer Klasse hinzuzufügen, und Sie werden Edge-Fälle treffen. Dies ist kein Bereich, in dem PHP glänzt. Wenn Sie es nicht gelesen haben, brauchen Sie * eine Kopie von "Effectively With Legacy Code" von Michael Feathers. – jeremiahd

+0

Danke. Ich werde class_alias versuchen. Ich schaue mir auch an, PHPUnit zu patchen und die verwendete Vorlage in eval() zu modifizieren. Was das Buch betrifft, was ich wirklich brauche, ist, die Chefs dazu zu bringen, etwas zu lesen. :) –