2010-05-18 12 views
6

Ich habe, was könnte als eine bizarre Hybrid von IQueryable<T> und IList<T> Sammlungen von Domain-Objekten gesehen, die meine Anwendung Stapel weitergegeben. Ich versuche, so viel wie möglich von der "späten Abfrage" oder "Lazy Loading" zu erhalten. Ich tue dies auf zwei Arten:Wie kann ich meine verzögerte Evaluierungs-/Ausführungsfunktionalität nachahmen oder testen?

  1. Durch eine LinqToSql Datenschicht unter Verwendung und Weitergabe IQueryable<T> s von Repositorys durch und meine App Schicht.
  2. Dann nach meiner App Ebene IList<T> s übergeben, aber wo bestimmte Elemente in der Objekt/Aggregat-Grafik sind 'chained' with delegates, so dass ihre Belastung zu verschieben. Manchmal sind sogar die Delegierteninhalte auf IQueryable<T> Quellen angewiesen und die DataContext sind injiziert.

Das funktioniert für mich bisher.

Was blendend schwierig ist, beweist, dass dieses Design tatsächlich funktioniert. Ie. Wenn ich irgendwo den "faulen" Teil besiege und meine Bewertung/Ausführung früh stattfindet, dann ist das Ganze eine Zeitverschwendung. Ich würde das gerne irgendwie tun können.

Ich weiß nicht viel über Delegierte oder Thread-Sicherheit, da es für Delegierte gilt, die auf der gleichen Quelle handeln. Ich möchte in der Lage sein, die DataContext zu verspotten und irgendwie verfolgen beide Methoden der Verschiebung (IQueryable<T> 's SQL und die Delegierten) das Laden, so dass ich Tests haben kann, die beweisen, dass beide Funktionen auf verschiedenen Ebenen/Ebenen der App arbeiten /Stapel.

Da es entscheidend ist, dass die Verschiebung für das Design von Wert ist, würde ich gerne sehen Tests fehlschlagen, wenn ich das Design auf einer bestimmten Ebene (getrennt von der Live-Implementierung) zu brechen. Ist das möglich?

Antwort

4

Bei morelinq haben wir eine so genannte "Breaking Sequence", um das zu testen. Im Grunde ist es ein Enumerator, der bei jeder Aufzählung eine Ausnahme auslöst.

Es kann so einfach sein wie:

internal sealed class BreakingSequence<T> : IEnumerable<T> 
{ 
    public IEnumerator<T> GetEnumerator() 
    { 
     throw new InvalidOperationException(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

Ein Test für sie wie folgt aussieht:

[Test] 
    public void XyzIsLazy() 
    { 
     var source = BreakingSequence<EntityClass>().AsQueryable(); 

     // inject it as your query source wherever appropriate 
     var query = source.Where(x=> true); 
     // does not throw, where does not enumerate the sequence 
    } 
+0

Klingt wie ein Anfang. Wie wäre es, wenn ich ein 'LazyItem ' habe, das Delegaten verwendet, um die Evaluierung des gekapselten Elements auszulösen? http: // Stapelüberlauf.com/questions/1669607/is-this-repository-pattern-effizient-mit-linq-to-sql/1695561 # 1695561 –

+0

@cottsak: Sie können den Delegaten als brechenden Delegaten festlegen (einen Delegaten, der eine Ausnahme auslöst). –

+0

Klingt nach einer guten Idee. Vielleicht war ich nach einer komplexeren Lösung, wenn es nicht notwendig war. –

2

ich in ähnlicher Weise zu dem, was Johannes Rudolph antwortete beantworten werde. Es klingt, als ob du das Richtige denkst und einen Test für etwas Wichtiges haben willst, das schwer zu verfolgen wäre, wenn es nicht funktioniert.

Ich würde definitiv vorschlagen, einen Mock für diesen Zweck zu verwenden. Johannes schlug ein Objekt vor, das eine Ausnahme auslöst, wenn es aufgezählt wird. Da es sich bei Ihrem Objekt um ein Template handelt, sollten Sie in der Lage sein, das gewünschte Objekt zu verwenden. Ein spöttisches Framework, wie Rhino.Mocks (free) oder TypeMock Isolator (teur), kann sehr hilfreich sein. Ich empfehle dringend, in mockende Frameworks zu schauen, wenn Sie das nicht schon getan haben.

Mit einem Mock in der Hand könnten Sie auswerten, dass Operationen in einer bestimmten Reihenfolge stattfinden sollen, wenn Sie bestimmten Testcode ausführen. Sie könnten Ihren Mock programmieren, um aufzuzeichnen, welche Vorgänge stattfinden, und dann die Aufzeichnung am Ende des Tests überprüfen.

+0

+1 für den Aufnahmevorschlag. Ich habe Mocks sehr leicht benutzt. Ich habe die "Aufnahme" -Muster gesehen, und das könnte eine gute Möglichkeit sein, eine ganze Reihe von komplexen Operationen in einem Test zusammenzubringen. Vielen Dank. –

+0

Ich habe den TypMock-Isolator evaluiert, habe aber entschieden, dass es für die wenigen Tests, die ich mache, zu teuer ist. Wenn Sie jedoch viele dieser Dinge testen möchten, stellen Sie vielleicht fest, dass das Einrichten Ihrer Tests oft so viel einfacher ist als bei anderen Frameworks. –

+0

Yeh ich weiß Rhino Mocks macht die Aufnahme Sache aber Moq schlägt vor, dass "Aufnahme" ist nicht so toll und es ist entworfen, nicht an diesem Ansatz zu halten - so werde ich vielleicht schauen, wie Moq die oben genannten erfüllen könnte. Vielleicht wird das eine Inspiration sein, wie man das testen kann. –

Verwandte Themen