Replizieren des Verhaltens von LINQ to Entities in Komponententests, die LINQ to Object verwenden

8

In meiner Lösung habe ich Komponententests, die nicht von der Datenbank abhängen, sondern Mocks und Integrationstests, die externe Abhängigkeiten wie die Datenbank haben.

Wenn ich Komponententests mit Mocks mache, wird LINQ to Object verwendet. Wenn die Integrationstests oder das echte Programm ausgeführt werden, wird LINQ to Entities verwendet und es ist strenger als LINQ to Object.

Gibt es eine Möglichkeit, das Verhalten von LINQ To Object in meinen Komponententests zu replizieren?

    
Gilles 21.06.2011, 18:48
quelle

3 Antworten

6

Sobald Ihre Unit-Testlogik mit IQueryable funktioniert, die von EF bereitgestellt wird, können Sie sie einfach nicht mit Unit-Tests testen, indem Sie EF spotten. Dies führt immer zu einem Wechsel von linq-to-entities zu linq-to-objects. Im Fall von etwas vereinfachtem ist der richtige Weg, dies im Komponententest zu handhaben, das Schreiben eines Fake statt des Mocks. Fake würde das Verhalten der Abhängigkeit simulieren. In diesem Fall bedeutet das Schreiben einer Fälschung, den EF-Provider zu schreiben, der an der In-Memory-Sammlung arbeitet, genauso wie der echte Provider mit der Datenbank arbeitet. Einen solchen Anbieter zu schreiben, ist wahrscheinlich das Projekt selbst.

Aus diesem Grund sollten Sie, sobald Ihre Logik linq-to-entities-Abfragen enthält, diese immer mit Integrationstests testen oder den Code so umgestalten, dass die Abfrage selbst in einer separaten Methode erfolgt (getestet durch Integrationstests) und die frühere Logik nun abhängig ist Klasse, die die Methode statt auf EF selbst enthält - dies führt zu einem Repository-Muster, in dem IQueryalbe nicht verfügbar gemacht wird, das Repository jedoch die Methode für jede benötigte Abfrage offen legt, die auf einer Entität operiert. Ich persönlich mag diese Art von Repositories nicht. Hier finden Sie aktuelle Diskussionen über verschiedene Repository-Implementierungen.

Wenn Sie sich dafür entscheiden, Integrationstests zu verwenden, die die Datenbank in In-Memory ändern, dann ist das möglich mit EFv4.1 und Code zuerst, wo Sie einfach die Verbindungszeichenfolge zu SQL Compact 4 ändern und es funktioniert (es sei denn, Sie verwenden spezielle Direkt-SQL) Aufrufe oder fordern einige spezielle SQL-Typen im Mapping). Im Falle einer EF mit EDMX-Datei wird es nicht funktionieren, da die EDMX-Datei eng mit der genauen Datenbankversion gekoppelt ist. Ein spezielles EDMX nur für Unit-Tests zu haben, ist keine Option, weil Sie anderen Code erneut testen würden.

Hier ist eine Reihe von verwandten Fragen , die Herausforderungen mit Einheitentest-EF-Code und Repositories diskutieren.

    
Ladislav Mrnka 21.06.2011, 23:00
quelle
0

Sie können das Repository-Muster zum Definieren der IRepository-Schnittstelle verwenden, in Ihrem tatsächlichen Code können Sie es mithilfe von Entity Framework implementieren, und in Ihrem Komponententest können Sie die Objekte zum Testen mithilfe von mock-Framework zurückgeben.

    
J.W. 21.06.2011 18:53
quelle
0

Wenn Sie möchten, dass Ihre Unit-Tests für die Ebene, die mit der Datenbank kommuniziert, den tatsächlichen Wert und alle Verhaltensweisen wie im Produktionscode haben, müssen Sie mit der Datenbank sprechen. Es kann als Verstoß gegen die Regel betrachtet werden, keine Abhängigkeiten im Komponententest zu haben, aber es gibt keine andere Möglichkeit, LINQ zu Entitäten auszuführen, als es mit der Datenbank real sprechen zu lassen. Es kann (und sollte wahrscheinlich) eine In-Memory-Datenbank sein - siehe zum Beispiel wie geht es Ayende? .

    
NOtherDev 21.06.2011 19:35
quelle