OO und testbar bleiben, während Sie mit einer Datenbank arbeiten

16

Welche OOP-Strategien gibt es, um mit einer Datenbank zu arbeiten, aber die Einheit testbar zu halten? Angenommen, ich habe eine Benutzerklasse und meine Produktionsumgebung funktioniert gegen MySQL. Ich sehe ein paar mögliche Ansätze, die hier mit PHP gezeigt werden:

  1. Übergeben Sie eine $ data_source mit Schnittstellen für load()und save(), um die Backend-Datenquelle zu abstrahieren. Übergeben Sie beim Testen einen anderen Datenspeicher.

    $ user = neuer Benutzer ($ mysql_data_source);
    $ user-> load ('bob');
    $ user-> setNickname ('Robby');
    $ user-> save ();
    
  2. Verwenden Sie eine Factory, die auf die Datenbank zugreift und die Ergebniszeile an den Konstruktor des Benutzers übergibt. Generieren Sie beim Testen den Parameter $ row manuell oder verspotten Sie das Objekt in UserFactory :: $ data_source. (Wie kann ich Änderungen am Datensatz speichern?)

    class UserFactory {
        static $data_source;
    
        public static function fetch( $username ) {
            $row = self::$data_source->get( [params] );
    
            $user = new User( $row );
            return $user;
        }
    }
    

Ich habe hier neben mir Design Patterns und Clean Code , aber ich habe Mühe, geeignete Konzepte zu finden.

Annika Backström
quelle

Antworten:

11

Was Sie also aufgreifen möchten, sind Martin Fowlers Muster der Unternehmensanwendungsarchitektur (er stellt hier auch einen Katalog auf seiner Website zur Verfügung ).

Darin beschreibt er verschiedene Muster zur Abstraktion des Datenzugriffs. Der erste Ansatz, den Sie beschreiben, ist Active Record . Ihr zweiter Ansatz ähnelt dem von Table Data Gateway .

Ein noch besserer Ansatz ist die Verwendung eines O / RM, um das manuelle Schreiben von Datenzugriffscode zu vermeiden. Ich habe PHP nicht verwendet, seit wir uns Sorgen um Y2K gemacht haben, aber Wikipedia hat eine Liste von Optionen für Sie . Ich weiß aber nicht, ob sie gut sind. Ich kann Ihnen jedoch einige Dinge sagen, nach denen Sie in einem O / RM Ausschau halten müssen:

  • Persistenz-Ignoranz : Der O / RM sollte Ihre Geschäftsobjekte nicht dazu zwingen, von einer bestimmten Schnittstelle / Klasse abgeleitet zu werden, um an der Datenzugriffsstrategie teilzunehmen.
  • Beziehungszuordnung : Sie sollten in der Lage sein, Beziehungen zwischen Ihren Objekten zuzuordnen (ein Kunde hat Aufträge, Aufträge haben Werbebuchungen, Werbebuchungen haben ein Produkt usw.).
  • Hierachische Zuordnung : Sie sollten in der Lage sein, Klassenhierarchien der Datenbank zuzuordnen.
  • Unterstützung für Abfragesyntax / -kriterien : Sie sollten in der Lage sein, zur Laufzeit eine Abfrage in Bezug auf Ihre Objekte und nicht in Bezug auf die Datenbank zu erstellen, und der O / RM sollte die Abfrage in der Datenbank übersetzen und ausführen. Zusätzliche Punkte, wenn die Abfrage eine stark typisierte Kette anstelle einer Zeichenfolge ist.

Es sind noch weitere Faktoren zu berücksichtigen, die jedoch zu den wichtigsten zählen. Hoffe das hilft.

Michael Brown
quelle
6

IMHO hängt es davon ab, was Sie testen möchten. Wenn Sie Ihre Geschäftslogik testen möchten, sollten Sie Ihren Datenzugriff stummschalten / verspotten ( Martin Fowler ), damit Ihr erster Vorschlag ein guter Anfang ist. Diese Stackoverflow-Frage enthält ein schönes C # -Beispiel (ich habe versucht, einige PHP-Beispiele zu finden, konnte aber keine finden).

Wenn Sie den Datenzugriff selbst testen möchten, wird er nicht mehr Unit-Test, sondern Integrationstest genannt. Lesen Sie hier eine allgemeine Anleitung. Diese Stapelüberlauf-Frage enthält auch einige interessante Links.

Wenn Sie die Logik gespeicherter Prozeduren in Ihrer Datenbank testen möchten, lesen Sie xUnit TestPattern

Hoffe das hilft

KeesDijk
quelle
2

Dies ist nicht unbedingt eine sofort hilfreiche Antwort. Wenn Sie sich jedoch wirklich Gedanken über die Testbarkeit von Datenbanken machen, sollten Sie sich überlegen, wie dies in Ruby on Rails geschieht. Soweit ich weiß, hat niemand das Thema besser oder intuitiver behandelt.

Adam Crossland
quelle
2
Ruby on Rails implementiert standardmäßig das Active Record-Muster.
Könnte
0

Ich empfehle Ihnen, die Symfony Framework-Lösung für diese Art von Problem zu überprüfen. Symfony ist ein PHP-OO-Framework mit Funktionstests.

Hier ist ein Link , sie haben so etwas wie das verwendet, worüber Sie nachdenken.

Guiman
quelle