Im Bereich der Softwareentwicklung ist das Testen unerlässlich, um sicherzustellen, dass Anwendungen korrekt und zuverlässig funktionieren. Dabei stehen Entwickler immer wieder vor der Herausforderung, externe Abhängigkeiten wie Drittanbieter-Bibliotheken oder APIs in ihre Tests zu integrieren. Viele empfinden es als selbstverständlich, diese Fremdkomponenten direkt durch sogenannte Mocks zu ersetzen, um unabhängige Testszenarien zu ermöglichen. Doch das Prinzip „Don’t Mock What You Don’t Own“, also „Mocke nicht, was dir nicht gehört“, stellt diese Herangehensweise infrage und bietet eine Alternative, die zahlreiche Vorteile mit sich bringt. Das Grundverständnis des Prinzips ist simpel: Entwickler sollen nur die Objekte oder Komponenten mocken, die sie selbst geschrieben oder kontrolliert haben.
Jeder Versuch, fremde Objekte zu mocken, führt häufig zu komplizierten, schwer wartbaren Tests, deren Aussagekraft oftmals leidet. Dieser Ansatz klingt zunächst kontraintuitiv, denn wie sollen komplexe externe Schnittstellen sonst spielend in Tests eingebunden werden? Ein schlüssiges Beispiel zeigt jedoch, wie durch ein intelligentes Schichtenmodell Tests übersichtlicher, robuster und intuitiver werden. Ein gängiges Einsatzgebiet für dieses Prinzip ist die Kommunikation mit Web-APIs, wie beispielsweise einem Docker-Registry-Server. Angenommen, ein Programm soll von solch einem Server eine Liste an Repositories inklusiver Tags abrufen. Auf den ersten Blick erscheint es naheliegend, eine HTTP-Bibliothek direkt im Business-Logic-Code zu verwenden und innerhalb der Tests diese Bibliothek durch Mock-Objekte zu simulieren.
Der umgesetzte Test benötigt dabei eine mehrschichtige Verschachtelung von Mocks, um die verschiedenen Antwortarten der API nachzubilden. Diese Mock-Konstrukte sind nicht nur komplex, sondern auch fragil, da selbst kleine Änderungen an der HTTP-Bibliothek oder der API die Tests zum Scheitern bringen können. Hier wird der Kernpunkt des Prinzips deutlich: Indem man direkt fremde Objekte mockt, entstehen Testfälle, die mehr über die Implementierung der Drittanbieter-Abhängigkeit aussagen als über den eigentlichen Geschäftslogikcode. Das führt zu Tests, die „Mock-Hölle“ genannt werden – schwer verständlich, leicht brüchig und mühsam zu pflegen. Eine weitaus elegantere Lösung ist es, eine eigene, minimalistische Abstraktionsschicht zu implementieren.
Statt die HTTP-Bibliothek direkt in der Geschäftslogik zu verwenden, erstellt man eine kleine Fassade oder Wrapper-Klasse, die nur wenige klar definierte Methoden anbietet. Im Beispiel wäre das zum Beispiel eine DockerRegistryClient-Klasse mit Methoden wie „get_repos()“ und „get_repo_tags(repo)“. Diese Klasse kapselt alle tieferen Details der HTTP-Kommunikation und dient als Schnittstelle zum restlichen System. Die entscheidende Veränderung im Testansatz ist nun, dass ausschließlich diese eigene Klasse gemockt wird. Da diese Fassade von den Testern kontrolliert wird, ist es viel einfacher, klare, übersichtliche Mock-Objekte zu erstellen, die nicht die volle Komplexität der Drittanbieter-API abbilden müssen.
Die Tests werden dadurch fokussierter auf die Businesslogik, weniger fragil gegenüber Änderungen externer Bibliotheken und es entsteht deutlich lesbarer Code, der die Intention des Tests unmittelbar erkennbar macht. Darüber hinaus erlaubt diese Strategie eine saubere Trennung von Verantwortlichkeiten. Die Fassade übernimmt die Aufgabe, den externen Dienst aufzurufen und darf ruhig etwas komplexer sein, während die Geschäftslogik selbst davon unberührt bleibt und so übersichtlich und simpel bleibt. Trotz der zusätzlichen Schicht bleibt der Code leicht verständlich und vor allem einfach testbar. Natürlich ist das Prinzip kein absoluter Dogma.
In manchen Situationen, gerade bei sehr einfachen notwendigen Tests oder wenn die API sehr stabil und gut abstrahiert ist, kann das direkte Mocken von Drittanbieter-Objekten pragmatisch sein. Wenn jedoch viele Tests, komplexe Interaktionen oder häufige Änderungen auftreten, empfiehlt sich die Indirektionsschicht dringend, gerade wegen der nachhaltigen Vorteile. Eine weitere positive Auswirkung dieser Vorgehensweise ist die Entkopplung der Businesslogik vom konkreten HTTP-Client oder anderen Drittanbieterklassen. Sobald die Geschäftslogik nur mit der eigenen Fassade interagiert, ist es einfacher, diese im Detail auszutauschen, z.B.
bei einem Wechsel der HTTP-Bibliothek, ohne dass eine Vielzahl von Tests angepasst werden muss. Unterm Strich lässt sich also festhalten, dass „Don’t Mock What You Don’t Own“ ein nützliches heuristisches Prinzip ist, das dazu einlädt, Softwarekomponenten sauber zu trennen und Tests verständlich und wartbar zu gestalten. Durch das bewusste Umschichten der Zuständigkeiten und das Reduzieren direkter Abhängigkeiten gewinnt das gesamte Projekt an Stabilität, und Entwickler sparen langfristig Zeit und Frustration. Wer tiefer in das Thema eintauchen möchte, findet in der Fachliteratur und einschlägigen Blogbeiträgen wertvolle Praxisbeispiele und weiterführende Diskussionen. Insbesondere das Buch „Architecture Patterns with Python“ liefert umfassende Einsichten zum Thema und unterstützt Entwickler dabei, moderne Architekturmuster in ihren Projekten erfolgreich umzusetzen.
Letztlich ist es eine Frage des Verständnisses und der Kompromisse. Entwickler sollten die Prinzipien nicht blind anwenden, sondern stets im Kontext des Projekts und der Anforderungen abwägen, wobei das Ziel stets Klarheit und Nachhaltigkeit in der Codebasis sein sollte. „Don’t Mock What You Don’t Own“ ist dabei ein wertvoller Leitstern auf dem Weg zu besserem Softwaredesign und effektiverem Testen.