Mock-Objekten in PHPUnit zu emulieren Statische Methode Aufrufe?
Ich versuche zum testen einer Klasse, die es schafft Daten-Zugriff in der Datenbank (Sie wissen, CRUD, im wesentlichen). Die DB-library die wir verwenden dazu ein API, wobei Sie zuerst das table-Objekt durch einen statischen Aufruf:
function getFoo($id) {
$MyTableRepresentation = DB_DataObject::factory("mytable");
$MyTableRepresentation->get($id);
... do some stuff
return $somedata
}
...Sie bekommen die Idee.
Versuchen wir testen diese Methode, aber Sie verspotten die DataObject-Zeug, so dass (a) wir brauchen eine tatsächliche db-Verbindung für den test, und (b) die wir nicht einmal brauchen, um die DB_DataObject lib für den test.
Jedoch in PHPUnit ich kann nicht scheinen, um $dies->getMock (), um entsprechend einrichten einer statischen Aufruf. Ich habe...
$DB_DataObject = $this->getMock('DB_DataObject', array('factory'));
...aber der test sagt noch unbekannte Methode "Fabrik". Ich weiß, es ist das Objekt erstellt haben, denn bevor er sagte, es konnte nicht finden, dass DB_DataObject. Jetzt kann es. Aber keine Methode?
Was ich wirklich tun wollen ist, mit zwei mock-Objekte, eines für das table-Objekt zurückgegeben, wie gut. Also, nicht nur muss ich angeben, dass factory ist ein statischer Aufruf, aber auch, dass es gibt einige bestimmte andere mock-Objekt, dass habe ich schon eingerichtet.
Sollte ich noch erwähnen, da ein Nachteil, dass ich Tat dies in SimpleTest eine Weile her (nicht den code) und es funktionierte gut.
Was gibt?
[UPDATE]
Bin ich angefangen zu begreifen, dass es etwas damit zu tun hat erwartet, dass()
Du musst angemeldet sein, um einen Kommentar abzugeben.
Stimme ich mit Euch beiden, dass es besser wäre, nicht um einen statischen Aufruf. Aber ich glaube, ich vergaß zu erwähnen, dass DB_DataObject ist eine Drittanbieter-Bibliothek, und der statische Aufruf Ihre best practice für Ihre code-Nutzung, nicht bei uns. Es gibt auch andere Möglichkeiten nutzen, um Ihre Objekte betreffen den Bau des zurückgegebenen Objekts direkt. Es bleibt nur diese verflixten include/require-Anweisungen in welcher Klasse auch immer-Datei mit, dass DB_DO Klasse. Das nervt, weil die tests brechen (oder eben auch nicht isoliert) wenn Sie mittlerweile versucht, die mock-Klasse mit dem gleichen Namen in Ihrem test--glaube ich zumindest.
Wenn Sie nicht ändern, die Bibliothek, ändern, Ihren Zugang es. Umgestalten Sie alle Aufrufe von DB_DataObject::factory() eine Instanz-Methode in Ihrem code:
Nun können Sie mit einer partiellen mock der Klasse, die Sie testen wollen und haben get erreichbar() zurück, ein mock-Tabelle-Objekt.
Dies ist ein gutes Beispiel für eine Abhängigkeit in Ihrem code, das design hat es unmöglich gemacht, um zu injizieren, in einem Mock, anstatt die echt Klasse.
Mein Erster Vorschlag wäre, zu versuchen und überarbeiten Sie den code für die Verwendung einer Instanz eher als ein statischer Aufruf.
Was fehlt (oder nicht?) von Ihrem DB_DataObject-Klasse ist ein setter übergeben eine vorbereitete db-Objekt vor dem Aufruf der factory-Methode. So können Sie ein mock oder ein custom db-Objekt (Gleiches interface), sollte die Notwendigkeit entstehen.
In deinem test-setup:
Die factory () - Methode zurückgeben soll, die verspottet DB-Instanz. Wenn es nicht bereits integriert in Ihrer Klasse, werden Sie wahrscheinlich haben, um die Umgestaltung der factory () - Methode als auch, es zu schaffen.
Sind, die Sie benötigen/einschließlich der class-Datei für DB_DataObject in den test-Fall? Wenn die Klasse nicht vorhanden ist, bevor versucht PHPUnit zu verspotten, das Objekt, das Sie bekommen können Fehler wie diese.
Mit PHPUnit MockFunction plus Erweiterung runkit können Sie auch mock-statische Methoden. Seien Sie vorsichtig, denn es ist monkey-patching und sollte daher nur verwendet werden, in extremen Fällen. Ersetzt kein guter Programmierstil.
https://github.com/tcz/phpunit-mockfunction