Assertions sind nützlich während der Entwicklung einer Anwendung, bei UnitTests können sie aber stören. Hier mal wieder ein Post aus der Kategorie „Gedankenstütze für mich, die vielleicht auch anderen hilft“, der das Deaktivieren von Assertions während der Ausführung von UnitTests beschreibt.

Bei UnitTests werden des Öfteren absichtlich Codepfade ausgeführt, die zur Laufzeit eigentlich niemals zur Ausführung kommen sollten, um das Verhalten einer Komponente im Fehlerfall zu testen. Wenn der Entwickler auf diesen Codepfaden Assertions eingefügt hat, was durchaus nützlich sein kann, führt dies beim Ausführen eines solchen Codepfads während eines UnitTests dazu, dass eine Meldung auf dem Bildschirm erscheint, welche „weggeklickt“ werden muss. Das hält natürlich den gesamten Ablauf der UnitTests auf, insbesondere dann, wenn diese auf einem Continuous Integration Server ausgeführt werden (was hoffentlich der Fall ist ;-)).

Der folgende Codeschnipsel zeigt, wie Assertions während der UnitTest-Ausführung unter MSTEST deaktiviert werden können.

[TestClass]
public class AssemblyInitialize {

    private static readonly object lockObject = new object();

    [AssemblyInitialize]
    public static void Initialize(TestContext context) {
        lock (lockObject) {
            TraceListener removeListener = Debug.Listeners.OfType().FirstOrDefault();
            if (removeListener != null) {
                Debug.Listeners.Remove(removeListener);
            }
        }
    }
}

Zur Funktionsweise

Wie in der Dokumentation im MSDN nachzulesen ist, hängt die Anzeige der Assertion-Meldungen davon ab, ob die Liste der Listener, die die Debug-Ausgabe überwachen, eine Instanz der Klasse DefaultTraceListener enthält. Wird diese also aus der Liste entfernt, werden die Meldungen nicht mehr angezeigt. Genau das macht die oben gezeigte Methode.
Die Methode wird mit dem Attribut AssemblyInitialize gekennzeichnet, so dass der darin enthaltene Code ausgeführt wird, bevor der erste UnitTest der Assembly gestartet wird. Zu beachten ist, dass die Methode in einer Testklasse (mit TestClass-Attribut gekennzeichnet) enthalten sein muss. Da diese Funktionalität i.d.R. keiner getesteten Klasse direkt zugeordnet werden kann, habe ich die Methode in eine eigene Klasse ausgelagert.

Die Assertion-Meldungen können in den Protokollen der TestRunner übrigens weiter eingesehen werden, wie auf der folgenden Abbildung zu sehen ist:

Ausgabe einer Assertion-Meldung im TestRunner-Protokoll von Visual Studio und ReSharper

Ausgabe einer Assertion-Meldung im TestRunner-Protokoll von Visual Studio und ReSharper

Update (03.04.2014)

Ein Kollege hat mich heute darauf aufmerksam gemacht, dass die Asserts auch per Konfigurationsdatei deaktiviert werden können. Sofern noch nicht vorhanden, muss dem UnitTest-Projekt eine solche (App.config) hinzugefügt werden. In dieser kann dann im Abschnitt System.Diagnostics ein Assert-Tag angegeben werden, über dessen Attribut AssertUiEnabled das Anzeigen der Assert-Dialoge deaktiviert werden kann. Eine einfache Konfigurationsdatei könnte so aussehen:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.diagnostics>
    <assert assertuienabled="true" />
  </system.diagnostics>
</configuration>

Wie auch in der programmatischen Lösung werden die Assert-Meldungen weiterhin im TestRunner-Protokoll angezeigt. Hier gibts auch noch die entsprechende Dokumentation im MSDN.