Frage

Ich versuche, eine Klasse zu testen, die den Datenzugriff in der Datenbank verwaltet (Sie wissen schon, CRUD, im Wesentlichen). Die DB-Bibliothek verwenden wir geschieht eine API haben, bei Ihnen zuerst das Tabellenobjekt durch einen statischen Aufruf erhalten:

function getFoo($id) {
  $MyTableRepresentation = DB_DataObject::factory("mytable");
  $MyTableRepresentation->get($id);
  ... do some stuff
  return $somedata
}

... Sie bekommen die Idee.

Wir versuchen, diese Methode zu testen, aber das Datenobjekt Zeug spöttisch, so dass (a) wir für den Test keine tatsächliche DB-Verbindung benötigen, und (b) wir die DB_DataObject lib nicht einmal enthalten müssen für den Test.

Doch in PHPUnit kann ich nicht scheinen, $ this- zu bekommen> getMock (), um in geeigneter Weise einen statischen Aufruf einrichten. Ich habe ...

        $DB_DataObject = $this->getMock('DB_DataObject', array('factory'));

... aber der Test sagt noch unbekannte Methode „Fabrik“. Ich weiß, dass es das Objekt erstellen, denn bevor sie sagte es nicht DB_DataObject finden kann. Jetzt kann es. Aber keine Methode?

Was will ich wirklich zu tun ist, zwei Mock-Objekte zu haben, eine für das Tabellenobjekt als auch zurückgegeben. Also, nicht nur muß ich das Werk angeben, ein statischer Aufruf ist, sondern auch, dass es gibt ein anderes Objekt mock angegeben, dass ich schon bereit.

Ich sollte als Einschränkung erwähnen, dass ich dies vor einer Weile tat in Simple (kann den Code nicht finden), und es hat gut funktioniert.

Was soll das?

[UPDATE]

Ich beginne zu begreifen, dass es etwas mit erwartet ()

zu tun
War es hilfreich?

Lösung

ich mit euch beiden einig, dass es besser wäre, nicht einen statischen Aufruf zu verwenden. Aber ich glaube, ich vergaß zu erwähnen, dass DB_DataObject ein Dritter Bibliothek ist, und die statischen Aufruf ist ihre Best Practice für ihre Code-Nutzung, nicht unsere. Es gibt auch andere Möglichkeiten, um ihre Objekte zu verwenden, die das zurückgegebene Objekt direkt beinhalten den Bau. Es lässt nur diejenigen gestopft sind / erfordern Aussagen in welcher Klassendatei, die DB_DO Klasse verwendet. Das saugt, weil die Tests brechen (oder einfach nicht isoliert werden), wenn Sie inzwischen sind versucht, eine Klasse mit dem gleichen Namen in Ihrem Test zu verspotten -. Zumindest ich denke,

Andere Tipps

Wenn Sie die Bibliothek nicht ändern können, ändern Sie Ihren Zugang davon. Umgestalten alle Anrufe DB_DataObject :: factory () zu einer Instanz-Methode in Ihrem Code:

function getFoo($id) {
  $MyTableRepresentation = $this->getTable("mytable");
  $MyTableRepresentation->get($id);
  ... do some stuff
  return $somedata
}

function getTable($table) {
  return DB_DataObject::factory($table);
}

Jetzt können Sie einen Teil-Mock der Klasse verwenden Sie testen und haben getTable () geben ein Mock-Tabellenobjekt.

function testMyTable() {
  $dao = $this->getMock('MyTableDao', array('getMock'));
  $table = $this->getMock('DB_DataObject', ...);
  $dao->expects($this->any())
      ->method('getTable')
      ->with('mytable')
      ->will($this->returnValue($table));
  $table->expects...
  ...test...
}

Dies ist ein gutes Beispiel für eine Abhängigkeit in Ihrem Code ist -. Das Design macht es unmöglich, in einem Mock zu injizieren, anstatt die reale Klasse

Mein erster Vorschlag wäre, um den Code zu versuchen und Refactoring eine Instanz zu verwenden, anstatt ein statischer Aufruf.

Was fehlt (oder nicht?) Von Ihrer DB_DataObject-Klasse ist ein Setter ein vorbereitetes db Objekt zu übergeben, bevor die Fabrik Methode aufrufe. So können Sie ein Modell oder ein benutzerdefinierten db-Objekt (mit der gleichen Schnittstelle) passieren können, sollte die Notwendigkeit entstehen.

In Ihrem Testaufbau:

 public function setUp() {
      $mockDb = new MockDb();
      DB_DataObject::setAdapter($mockDb);
 }

Die Fabrik () Methode sollte die verspottete DB-Instanz zurück. Wenn es nicht schon in die Klasse integriert ist, werden Sie wahrscheinlich die Fabrik () -Methode als auch haben, Refactoring, damit es funktioniert.

Sie benötigen / einschließlich der Klassendatei für DB_DataObject in Ihrem Testfall? Wenn die Klasse nicht existiert, bevor PHPUnit um das Objekt zu verspotten versucht, können Sie Fehler wie diese erhalten.

Mit PHPUnit MockFunction Erweiterung und runkit Sie auch statische Methoden verspotten. Seien Sie vorsichtig, weil es Affen Patchen ist und sollten deshalb nur in Extremfällen eingesetzt werden. Ersetzt nicht gute Programmierpraktiken.

https://github.com/tcz/phpunit-mockfunction

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top