Unit Testing im Mittelstand: Was Nick Chapsas nicht sagt (und warum das kein Vorwurf ist)

Nick Chapsas erklärt Unit Testing in .NET technisch sauber. Was er nicht beschreibt: wie das in einem Betrieb mit 40 Mitarbeitenden und einem einzigen .NET-Entwickler wirklich landet.

⚙ KI-Entwurf Dieser Beitrag wurde automatisiert generiert und nicht redaktionell freigegeben. Behandelt ihn entsprechend.

Letzten Herbst war ich bei einem Maschinenbauer im Raum Stuttgart. 180 Mitarbeitende, Familienunternehmen, solide. Der einzige interne Entwickler — nennen wir ihn Markus — pflegt seit sieben Jahren eine .NET-Eigenentwicklung für Auftragssteuerung und Warenwirtschaft. Rund 60.000 Zeilen Code, keine Tests, kein CI/CD. Als ich fragte, warum, war die Antwort ehrlich: "Ich weiß, dass ich Tests schreiben sollte. Aber ich weiß nicht, wo ich anfangen soll, und ich habe keine Zeit, einen halben Monat in etwas zu investieren, das im ersten Schritt nichts sichtbar verbessert."

Das ist kein Einzelfall. Das ist der Normalzustand in deutschen KMU mit selbst entwickelter Software. Und genau hier liegt die Lücke zwischen dem, was gute Tutorial-Artikel erklären, und dem, was in der Praxis tatsächlich hilft.

Was Nick Chapsas schreibt

Nick Chapsas ist einer der kompetentesten .NET-Blogger, die ich kenne. Sein Artikel zu Unit Testing in .NET erklärt sauber, was Unit Tests sind, warum sie zählen und wie man mit XUnit und NSubstitute in der Praxis loslegt. Er zeigt das Arrange-Act-Assert-Pattern, erklärt den Unterschied zwischen [Fact] und [Theory], demonstriert parametrisierte Tests mit InlineData und führt anschließend Mocking mit NSubstitute ein — am Beispiel eines NotificationService, der einen IEmailSender injiziert bekommt.

Technisch ist das alles korrekt und gut erklärt. XUnit ist meine erste Wahl, NSubstitute ebenfalls — da bin ich vollständig bei ihm. Der Artikel ist genau das, was er sein soll: ein solider Einstieg für .NET-Entwickler, die Unit Testing noch nicht kennen oder auffrischen wollen.

Was er nicht ist: eine Anleitung für Markus.

Wie das im KMU wirklich landet

Lass mich konkret werden. Wenn ein Solo-Entwickler oder ein kleines Team in einem Mittelstandsbetrieb anfängt, Unit Tests zu schreiben, treffen sie auf drei Probleme, die in keinem Tutorial auftauchen:

Problem 1: Die bestehende Codebasis ist nicht testbar.

Ein frisch gegründetes Startup kann seine Architektur auf Testbarkeit ausrichten. Dependency Injection, saubere Interfaces, Separation of Concerns. Wer seit sieben Jahren gewachsenen Code hat, der hat oft das Gegenteil: statische Methoden, direkte Datenbankzugriffe, Business-Logik in Code-Behind-Dateien oder Windows-Forms-Eventhandlern. Das Calculator-Beispiel aus dem Artikel testet sich in fünf Minuten. Aber niemand schreibt im Mittelstand Code, der wie Calculator aussieht — der testet sich sowieso schon durch Hingucken.

Der erste Schritt für Markus ist also nicht "XUnit installieren", sondern verstehen, wie man Legacycode überhaupt erst testbar macht. Das ist ein anderes Thema — und ein schwereres.

Problem 2: 80 % des Geschäftswerts stecken in der Datenbanklogik.

Nick Chapsas mockt den IEmailSender weg, weil man E-Mails nicht wirklich in einem Unit Test versenden will. Das ergibt Sinn. Aber wenn ich mir anschaue, wo in Mittelstands-Applikationen echte Fehler entstehen, dann ist die Antwort fast immer: in der Datenbanklogik. Falsche JOINs, falsche Aggregationen, Race Conditions beim gleichzeitigen Buchen, fehlende Transaktionen. Genau das, was Unit Tests mit Mocks nicht abdecken.

Das heißt nicht, dass Unit Tests wertlos sind. Aber wenn Markus fünf Stunden im Monat für Tests hat, dann bringt ihm ein Integrationstest gegen eine echte Testdatenbank mehr als zehn gemockte Unit Tests. In einer Welt mit knappen Ressourcen ist die Frage nicht "Unit Tests oder gar nichts?", sondern "welche Teststrategie ergibt für diesen Betrieb das beste Kosten-Nutzen-Verhältnis?"

Problem 3: Tests, die niemand pflegt, sind schlimmer als keine Tests.

Das ist der Punkt, der am häufigsten übersehen wird. Ich habe Mandate gesehen, wo in einem Aktionismus-Sprint Hunderte Unit Tests geschrieben wurden — alle grün, alle sinnlos, weil sie nur gemockte Mocks testeten. Sechs Monate später waren zwei Drittel davon kaputt (wegen Umstrukturierungen) und wurden in der Pipeline auf skip gesetzt. Danach hat niemand mehr in die Testsuite geschaut.

Tests, die nicht gepflegt werden, erzeugen das Schlimmste: falsches Sicherheitsgefühl. Wenn die Pipeline grün ist und der Entwickler denkt "ist alles okay", aber die Tests decken schon längst nichts Kritisches mehr ab — das ist aktiv gefährlicher als kein Test.

Meine konkrete Empfehlung für KMU

Wenn ich Markus berate, sage ich ihm folgendes — in dieser Reihenfolge:

Schritt 1: Nicht mit dem schwierigsten Code anfangen. Finde die drei bis fünf reinen Business-Logik-Funktionen in deiner Applikation, die keine Datenbankzugriffe haben und die du jetzt schon testen kannst. Preisberechnung, Rabattlogik, Validierungsregeln, Datumsarithmetik. Genau das, was Nick Chapsas mit dem Calculator zeigt. Fang dort an. Nicht weil das die wichtigsten Tests sind, sondern weil du lernen musst, wie sich ein gutes Test-Setup anfühlt, bevor du die schwierigen Fälle angehst.

Schritt 2: Integriere Tests in die tägliche Arbeit, nicht als Projekt. Kein "wir schreiben jetzt zwei Wochen nur Tests". Stattdessen: Jeder neue Bug bekommt einen Regressionstest, bevor der Fix eingecheckt wird. Das ist in 30 Minuten gelernt, bringt sofort Mehrwert und baut die Testsuite organisch auf.

Schritt 3: Für die Datenbanklogik: Integrationstests, keine Mocks. Richte eine Testdatenbank ein (lokal oder in der Pipeline per Docker), und schreib Tests, die echte SQL-Queries ausführen. Das ist aufwändiger in der Einrichtung, aber die Fehler, die du damit findest, sind echte Fehler — nicht Artefakte deiner Mock-Konfiguration.

Schritt 4: CI/CD first, Abdeckung second. Bevor du über Testabdeckung nachdenkst: Lass die Tests in einer Pipeline laufen. GitHub Actions, Azure DevOps, egal. Wenn Tests nur lokal laufen, laufen sie irgendwann gar nicht mehr. Pipeline-Integration kostet einen Nachmittag und macht den ganzen Aufwand erst wertvoll.

XUnit und NSubstitute — genau wie Nick Chapsas empfiehlt — sind dabei die richtigen Werkzeuge. Daran ändert sich nichts. Es geht nur um die Reihenfolge der Schritte und darum, realistische Erwartungen zu setzen.

Ein Betrieb mit einem Entwickler wird keine 80 % Testabdeckung erreichen und sollte es auch nicht anstreben. Was er erreichen kann: eine handvoll verlässlicher Tests für die kritischste Business-Logik, ein Regressionsnetz für bekannte Bugs, und eine funktionierende Pipeline. Das ist kein schlechtes Ergebnis — das ist pragmatisches Engineering.


Der vollständige Original-Beitrag von Nick Chapsas: Getting Started with Unit Testing in .NET


Wenn du gerade in einer ähnlichen Situation bist — gewachsener Code, kein Testnetz, keine Zeit für einen Big-Bang-Umbau — dann rede ich gerne 30 Minuten Klartext mit dir über einen realistischen Einstieg.

30 Min Klartext-Sparring

— Bernhard