8 Stimmen

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

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

Wenn ich Unit-Tests mit Mocks durchführe, wird LINQ to Object verwendet. Wenn die Integrationstests oder das echte Programm ausgeführt werden, wird LINQ to Entities verwendet, das strenger ist als LINQ to Object.

Gibt es eine Möglichkeit, LINQ To Object strengeres Verhalten in meine Unit-Tests zu replizieren?

6voto

Ladislav Mrnka Punkte 355028

Sobald Ihre einheitlich getestete Logik mit IQueryable von EF zur Verfügung gestellt wird, können Sie es nicht mit Unit-Tests testen, indem Sie EF spiegeln. Das wird immer dazu führen, dass man von Linq-to-Entities zu Linq-to-Objects wechselt. Im Falle von etwas Vereinfachtem ist der korrekte Weg, dies in Unit-Tests zu behandeln, ein Fake anstelle eines Mocks zu schreiben. Fake würde das Verhalten der Abhängigkeit simulieren. In diesem Fall bedeutet das Schreiben eines Fakes, dass der EF-Anbieter mit der In-Memory-Sammlung genauso arbeitet wie der echte Anbieter mit der Datenbank. Das Schreiben eines solchen Anbieters ist wahrscheinlich ein eigenes Projekt.

Aus diesem Grund sollten Sie, sobald Ihre Logik Linq-to-Entities-Abfragen enthält, diese immer mit Integrationstests testen oder den Code so umstrukturieren, dass die Abfrage selbst in einer separaten Methode enthalten ist (die von Integrationstests getestet wird) und die frühere Logik nun von der Klasse abhängt, die die Methode enthält, anstatt von EF selbst - dies führt zu einem Repository-Muster, bei dem IQueryalbe ist nicht offengelegt, aber das Repository legt für jede benötigte Abfrage, die auf eine Entität wirkt, eine Methode offen. Ich persönlich mag diese Art von Repositories nicht. Hier eine aktuelle Diskussion über verschiedene Repository-Implementierungen.

Wenn Sie sich für Integrationstests entscheiden, kann die Umstellung der Datenbank auf eine In-Memory-Datenbank mit EFv4.1 und dem ersten Code möglich sein. Ändern Sie einfach die Verbindungszeichenfolge in SQL Compact 4 und es wird funktionieren (es sei denn, Sie verwenden einige spezielle direkte SQL-Aufrufe oder verlangen einige spezielle SQL-Typen im Mapping). Im Falle von EF mit EDMX-Datei wird es nicht funktionieren, da die EDMX-Datei eng mit der genauen Datenbankversion gekoppelt ist. Eine spezielle EDMX-Datei nur für Unit-Tests zu haben, ist keine Option, da Sie dann wieder anderen Code testen würden.

Hier finden Sie eine Reihe von Fragen zum Thema Erörterung der Herausforderungen beim Unit-Testing von EF-Code und Repositories.

0voto

J.W. Punkte 17431

Sie können das Repository-Pattern verwenden, um die IRepository-Schnittstelle zu definieren. In Ihrem eigentlichen Code können Sie sie mit Entity Framework implementieren, und in Ihrem Unit-Test können Sie Mock Framework verwenden, um die Objekte für den Test zurückzugeben.

0voto

NOtherDev Punkte 9422

Wenn Sie möchten, dass Ihre Unit-Tests für die Schicht, die mit der Datenbank kommuniziert, den tatsächlichen Wert und alle Verhaltensweisen wie im Produktionscode haben, müssen Sie mit der Datenbank kommunizieren. Es mag als Bruch der Regel angesehen werden, keine Abhängigkeiten in Unit-Tests zu haben, aber es gibt keinen anderen Weg, LINQ to Entities seine Arbeit machen zu lassen, als es mit real Datenbank. Es kann (und sollte wahrscheinlich) eine In-Memory-Datenbank sein - siehe zum Beispiel Wie macht Ayende das? .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X