Ich habe eine MVC-Webanwendung und verwende Simple Injector für DI. Fast mein gesamter Code wird von Komponententests abgedeckt. Jetzt, da ich einige Telemetrieaufrufe in einigen Controllern hinzugefügt habe, habe ich Probleme, die Abhängigkeiten einzurichten.
Die Telemetrieaufrufe dienen zum Senden von Messwerten an den von Microsoft Azure gehosteten Application Insights-Dienst. Die App läuft nicht in Azure, nur ein Server mit ISS. Das AI-Portal informiert Sie über alle Arten von Anwendungen, einschließlich benutzerdefinierter Ereignisse, die Sie mit der Telemetriebibliothek senden. Daher benötigt der Controller eine Instanz von Microsoft.ApplicationInsights.TelemetryClient, die keine Schnittstelle hat und eine versiegelte Klasse mit 2 Konstruktoren ist. Ich habe versucht, es so zu registrieren (der hybride Lebensstil hat nichts mit dieser Frage zu tun, ich habe sie nur der Vollständigkeit halber aufgenommen):
%Vor%Das Problem besteht darin, dass SI, da der TelemetryClient über zwei Konstruktoren verfügt, sich beschwert und die Validierung nicht besteht. Ich habe einen Post gefunden, der zeigt, wie das Konstruktorauflösungsverhalten des Containers überschrieben werden kann, aber das scheint ziemlich kompliziert zu sein. Zuerst wollte ich sichern und diese Frage stellen:
Wenn ich den TelemetryClient nicht zu einer injizierten Abhängigkeit mache (nur eine Neue in der Klasse erstellen), wird diese Telemetrie bei jedem Durchlauf des Komponententests an Azure gesendet, wodurch viele falsche Daten entstehen? Oder ist Application Insights intelligent genug, um zu wissen, dass es in einem Komponententest ausgeführt wird und nicht die Daten sendet?
Irgendwelche "Einblicke" in dieses Problem würden sehr geschätzt werden!
Danke
Microsoft.ApplicationInsights.TelemetryClient, das keine Schnittstelle hat und eine versiegelte Klasse mit 2 Konstruktoren ist.
Diese TelemetryClient
ist ein Framework-Typ und Framework-Typen sollten nicht von Ihrem Container automatisch verkabelt werden .
Ich habe einen Beitrag gefunden, der zeigt, wie das Konstruktorauflösungsverhalten des Containers überschrieben wird, aber das scheint ziemlich kompliziert zu sein.
Ja, diese Komplexität ist absichtlich, weil wir Menschen davon abhalten wollen, Komponenten mit mehreren Konstruktoren zu erstellen, denn dies ist ein Anti-Muster .
Anstatt Auto-Wiring zu verwenden, können Sie, wie @qujck bereits sagte, einfach die folgende Registrierung vornehmen:
%Vor%Oder ist Application Insights intelligent genug, um zu wissen, dass es in einem Komponententest ausgeführt wird und nicht die Daten sendet?
Sehr unwahrscheinlich. Wenn Sie die Klasse testen möchten, die von diesem TelemetryClient
abhängt, sollten Sie stattdessen eine falsche Implementierung verwenden, um zu verhindern, dass Ihr Komponententest fragil oder langsam wird oder Ihre Insight-Daten verschmutzt. Aber selbst wenn das Testen keine Rolle spielt, sollten Sie nach dem Prinzip der Abhängigkeitsinversion von (1) Abstraktionen abhängig sein (2) durch Ihre eigene Anwendung definiert. Sie scheitern beide Punkte, wenn Sie TelemetryClient
verwenden.
Stattdessen sollten Sie eine (oder sogar mehrere) Abstraktionen über die TelemetryClient
definieren, die speziell auf Ihre Anwendung zugeschnitten sind . Versuchen Sie also nicht, die API TelemetryClient
mit ihren möglichen 100 Methoden nachzuahmen, sondern definieren Sie nur Methoden auf der Schnittstelle, die Ihr Controller tatsächlich verwendet, und machen Sie sie so einfach wie möglich. Machen Sie den Code des Controllers einfacher - und Ihr Unit-Test einfacher.
Nachdem Sie eine gute Abstraktion definiert haben, können Sie eine Adapterimplementierung erstellen, die das TelemetryClient
intern verwendet. Ich stelle fest, dass Sie diesen Adapter wie folgt registrieren:
Hier gehe ich davon aus, dass TelemetryClient
Thread-sicher ist und als Singleton funktionieren kann. Andernfalls können Sie Folgendes tun:
Hier ist der Adapter immer noch ein Singleton, aber er ist mit einem Delegaten ausgestattet, der die Erstellung von TelemetryClient
ermöglicht. Eine andere Möglichkeit besteht darin, den Adapter das TelemetryClient
intern erstellen (und vielleicht entsorgen) zu lassen. Das würde vielleicht die Registrierung noch einfacher machen:
Wenn Sie nicht in den Abstraktions- / Wrapper-Pfad gehen wollen. In Ihren Tests könnten Sie den AppInsights-Endpunkt einfach an einen simulierten Lightweight-HTTP-Server verweisen (was in ASP.NET Core trivial ist).
appInsightsSettings.json
%Vor%So richten Sie "TestServer" in ASP.NET Core ein Ссылка
Tags und Links azure c# unit-testing azure-application-insights simple-injector