ASP.NET-Infrastruktur in MediatR-Handlern

8

Ich bevorzuge es, meine Handler frei von ASP.NET-Infrastruktur zu halten, die sehr schwer zu testen ist (ja, sogar in ASP.NET Core). Aber manchmal passiert es, und Sie haben eine Abhängigkeit wie UserManager (ich möchte eines Tages wissen, warum es keine Schnittstelle ist), HttpContext usw. und Komponententests werden in eine Spott-Hölle verwandelt.

Ich habe versucht, Integrationstests dafür zu verwenden, indem ich einen TestServer erstellte und die gesamte ASP.NET-Infrastruktur für jeden API-Aufruf initialisiert habe. Es funktioniert ganz gut, aber manchmal scheint es wie ein Overkill, wenn ich die einfache Logik meines Handlers testen möchte. Und während es das technische Problem der ASP.NET-Infragestellung löst, behebt es das Architekturproblem (wenn man es so betrachtet), ASP.NET-Infrastruktur in seinen Handlern zu haben.

Ich würde gerne wissen, was die empfohlenen Ansätze sind, um damit umzugehen?

    
SiberianGuy 30.01.2017, 08:58
quelle

3 Antworten

3

Ich fühle deinen Schmerz. Ich bin über einen fantastischen Blob Post gestolpert von Jimmy Bogard, der dieses Problem behandelt, indem er das verwendet, was Martin Fowler Subkutane Tests nennt. Ich werde den Experten die tiefe Erklärung überlassen, aber in aller Kürze vermeiden subkutane Tests einfach alle schwierig zu testenden Aspekte der Benutzeroberfläche.

Schamloser Stecker: Ich schreibe gerade ein Wiki Diese Muster werden in einem Beispiel-End-to-End-Projekt auf GitHub demonstriert. Es ist nicht schwer zu folgen, aber es ist wahrscheinlich zu viel Code für eine SO-Antwort.

Um zusammenzufassen:

  • Wenn Sie MediatR korrekt verwenden, sollten Ihre Controller sehr dünn sein, was das Testen sinnlos macht.
  • Was Sie testen möchten, sind Ihre Handler.
  • Sie möchten jedoch Ihre Handler als Teil Ihrer realen Pipeline testen.

Zu lösen:

  1. Wickeln Sie die HTTP-Anfrage in eine Transaktion ein.
  2. Erstellen Sie eine Testvorrichtung, die die Anwendungen Startup.cs
  3. nachahmt
  4. Richten Sie einen Test-DB-Server ein, um Abfragen auszuführen, und wird nach jedem Test zurückgesetzt.

Das ist es im Grunde genommen. Jedes Mal, wenn Sie einen Integrationstest für einen Ihrer Handler ausführen:

  • Die Hosting-Umgebung wird verspottet, aber Ihre Anwendung wird in einem realen Test gestartet.
  • Ihre Abfrage oder Ihr Befehl ist in eine Transaktion eingebettet, die Ihren DbContext nachahmt.
  • Der Handler wird gegen eine echte Datenbank ausgeführt und dann zurückgesetzt.

Ich würde meiner Antwort weitere Codebeispiele hinzufügen, aber zwischen dem Blogpost und dem Wiki, das ich bereitgestellt habe, ist es viel einfacher, den Codebeispielen zu folgen.

    
trevorc 07.02.2017 15:34
quelle
1

Ich würde sagen, es hängt vom Grad des Selbstvertrauens ab, den Sie am Ende haben wollen. Wenn Sie sicherstellen möchten, dass das gesamte System wie erwartet funktioniert, dann sind Integrationstests mit TestServer wahrscheinlich der richtige Weg.

Ein Vorteil von MediatR ist jedoch, dass Sie Ihre Geschäftslogik von der Anwendung, die sie verwendet, entkoppeln können. Aus diesem Grund gibt es auf der obersten Ebene, sagen wir in Controllern, keine Logik, sondern nur eine Delegation an den Mediator.

Damit haben Sie recht, dass Ihre Logik manchmal Informationen von der Hosting-Anwendung benötigt. Ein Beispiel wäre der Benutzer, der die Anfrage stellt, auf die im HTTP-Kontext zugegriffen werden kann.

Wenn Sie in diesem Fall vermeiden möchten, dass Sie einen Test-HTTP-Server zum Testen Ihrer Logikfunktionen einrichten müssen, können Sie diese Informationen in einer Abstraktion darstellen, und Ihr Handler würde dann eine Abhängigkeit von dieser Abstraktion übernehmen. Ihre Tests könnten dann diese Abhängigkeit verspotten, während Sie das reale System für alles andere verwenden.

Macht das Sinn?

    
Mickaël Derriey 02.02.2017 00:06
quelle
1

Mediatr oder nein, Sie sollten immer versuchen, nur sehr grundlegende Logik in Ihren Controllern zu übergeben und Business Intelligence-Klassen von dort injizieren, um die eigentliche Arbeit zu tun. Wenn Sie ihnen Schnittstellen zu dieser Geschäftslogik hinzufügen, werden die Abhängigkeiten Ihrer Controller in Ihren Komponententests leicht verspottet und Ihre Tests können sich darauf konzentrieren, ob sie diese Schnittstellen richtig implementieren und nur die grundlegende Arbeit der Routing-Eingabe / Ausgabe ausführen. Und Ihre eigentliche Geschäftslogik kann noch einfacher getestet werden.

Für die Klassen, die statisch sind, zum Beispiel zum Lesen der web.config-Einstellungen, ist eine Strategie, die ich sehr mag, eine Wrapper-Klasse um sie herum. Während der ConfigurationManager statisch ist, kann ich immer noch eine reguläre Klasse mit einer Schnittstelle schreiben, der Methoden oder Eigenschaften hinzugefügt werden, um eine bestimmte Einstellung (vorzugsweise semantisch benannt) aus dem Konfigurationsmanager zu lesen. Jetzt kann ich jede konfigurierte Einstellung (oder Abwesenheit davon) in meinem Test leicht verspotten, indem ich nur die Schnittstelle verspotte und verschiedene Rückgabewerte einrichte.

    
Arwin 02.02.2017 19:19
quelle