Ein Repository übersetzt von Ihrer Domain in Ihr DAL-Framework wie NHibernate oder Doctrine oder in Ihre SQL-ausführenden Klassen. Dies bedeutet, dass Ihr Repository Methoden für dieses Framework aufruft, um seine Aufgaben auszuführen: Ihr Repository erstellt die Abfragen, die zum Abrufen der Daten erforderlich sind. Wenn Sie kein ORM-Framework verwenden (ich hoffe, Sie sind ...), ist das Repository der Ort, an dem rohe SQL-Anweisungen erstellt werden.
Die grundlegendste dieser Methoden ist das Speichern: In den meisten Fällen wird das Objekt einfach aus dem Repository an die Arbeitseinheit (oder die Sitzung) übergeben.
public void Save(Car car)
{
session.Save(car);
}
Aber schauen wir uns ein anderes Beispiel an, zum Beispiel das Abrufen eines Autos anhand seiner ID. Es könnte so aussehen
public function GetCarWithId(String id)
{
return Session.QueryOver<Car>()
.Where(x => x.Id == id)
.SingleOrDefault();
}
Immer noch nicht zu komplex, aber Sie können sich vorstellen, dass dies unter verschiedenen Bedingungen (lassen Sie mir alle Autos nach 2010 für alle Marken der Volkswagen-Gruppe herstellen) schwierig wird. Auf echte TDD-Art müssen Sie dies also testen. Es gibt verschiedene Möglichkeiten, dies zu tun.
Option 1: Verspotten Sie die Aufrufe des ORM-Frameworks
Natürlich können Sie das Session-Objekt verspotten und einfach behaupten, dass die richtigen Aufrufe getätigt werden. Während dies das Repository testet, ist es nicht wirklich testgetrieben , da Sie nur testen, ob das Repository intern so aussieht, wie Sie es möchten. Der Test sagt im Grunde, dass der Code so aussehen sollte. Trotzdem ist es ein gültiger Ansatz, aber es scheint, dass diese Art von Test sehr wenig Wert hat.
Option 2: Erstellen Sie die Datenbank aus den Tests (neu)
Einige DAL-Frameworks bieten Ihnen die Möglichkeit, die vollständige Struktur der Datenbank basierend auf den Zuordnungsdateien zu erstellen, die Sie erstellen, um die Domäne den Tabellen zuzuordnen. Bei diesen Frameworks besteht die Möglichkeit zum Testen von Repositorys häufig darin, im ersten Schritt des Tests die Datenbank mit einer In-Memory-Datenbank zu erstellen und der In-Memory-Datenbank Objekte mithilfe des DAL-Frameworks hinzuzufügen. Danach können Sie das Repository in der In-Memory-Datenbank verwenden, um zu testen, ob die Methoden funktionieren. Diese Tests sind langsamer, aber sehr gültig und führen zu Ihren Tests. Es erfordert eine gewisse Zusammenarbeit von Ihrem DAL-Framework.
Option 3: Test an einer tatsächlichen Datenbank
Ein anderer Ansatz besteht darin, eine tatsächliche Datenbank zu testen und die unittest zu isolieren. Sie können dies auf verschiedene Arten tun: Umgeben Sie Ihre Tests mit einer Transaktion, bereinigen Sie sie manuell (würde nicht als sehr schwer zu warten empfehlen), erstellen Sie die Datenbank nach jedem Schritt vollständig neu ... Abhängig von der Anwendung, die Sie erstellen, kann dies oder möglicherweise nicht machbar sein. In meinen Anwendungen kann ich eine lokale Entwicklungsdatenbank vollständig aus der Quellcodeverwaltung erstellen, und meine Unittests in Repositorys verwenden Transaktionen, um die Tests vollständig voneinander zu isolieren (offene Transaktion, Daten einfügen, Test-Repository, Rollback-Transaktion). Jeder Build richtet zuerst die lokale Entwicklungsdatenbank ein und führt dann transaktionsisolierte Unittests für die Repositorys in dieser lokalen Entwicklungsdatenbank durch. Es'
Testen Sie den DAL nicht
Wenn Sie ein DAL-Framework wie NHibernate verwenden, müssen Sie dieses Framework nicht testen. Sie können Ihre Zuordnungsdateien testen, indem Sie ein Domänenobjekt speichern, abrufen und dann vergleichen, um sicherzustellen, dass alles in Ordnung ist (deaktivieren Sie unbedingt jede Art von Caching), aber es ist nicht so erforderlich wie viele andere Tests, die Sie schreiben sollten. Ich mache dies meistens für Sammlungen von Eltern mit Bedingungen für die Kinder.
Wenn Sie die Rückgabe Ihrer Repositorys testen, können Sie einfach überprüfen, ob eine identifizierende Eigenschaft Ihres Domänenobjekts übereinstimmt. Dies kann eine ID sein, aber in Tests ist es oft vorteilhafter, eine vom Menschen lesbare Eigenschaft zu überprüfen. In "Hol mir alle Autos, die nach 2010 hergestellt wurden ..." könnte einfach überprüft werden, ob fünf Autos zurückgegeben wurden und die Nummernschilder "Liste hier einfügen" sind. Ein zusätzlicher Vorteil ist, dass Sie gezwungen sind, über das Sortieren nachzudenken, UND Ihr Test die Sortierung automatisch erzwingt. Sie wären überrascht, wie viele Anwendungen entweder mehrmals sortieren (aus der Datenbank sortiert zurückgeben, vor dem Erstellen eines Ansichtsobjekts sortieren und dann das Ansichtsobjekt sortieren, alle für alle Fälle auf derselben Eigenschaft ) oder implizit davon ausgehen, dass das Repository sortiert und versehentlich entfernt wird das war irgendwo auf dem Weg und brach die Benutzeroberfläche.
'Unit Test' ist nur ein Name
Meiner Meinung nach sollten Unit-Tests meistens nicht in die Datenbank gelangen. Sie erstellen eine Anwendung so, dass jeder Code, der Daten aus einer Quelle benötigt, dies mit einem Repository tut und dieses Repository als Abhängigkeit eingefügt wird. Dies ermöglicht ein einfaches Verspotten und die gewünschte TDD-Güte. Aber am Ende möchten Sie sicherstellen, dass Ihre Repositorys ihre Aufgaben erfüllen, und wenn der einfachste Weg, dies zu tun, darin besteht, eine Datenbank zu erreichen, dann sei es so. Ich habe die Vorstellung, dass Unit-Tests die Datenbank nicht berühren sollten, lange losgelassen und festgestellt, dass es sehr reale Gründe dafür gibt. Aber nur, wenn Sie dies automatisch und wiederholt tun können. Und das Wetter, das wir einen solchen Test als "Unit Test" oder "Integrationstest" bezeichnen, ist umstritten.