Mocking-Bibliotheken für Typescript

In meinem letzten Blog-Beitrag habe ich mich damit beschäftigt, wie beim Testen von Typescript-Code Abhängigkeiten mithilfe von Jest gemockt werden können. Da das Erstellen von Mocks mit Jest aber zum Teil etwas umständlich war, möchte ich in diesem Beitrag als Alternative hierzu die Mocking-Bibliotheken TypeMoq und ts-mockito vorstellen. Jest wird als Test-Bibliothek weiterhin zum Einsatz kommen, jedoch nicht mehr zum Erstellen von Mocks verwendet werden.

Überblick

Natürlich wäre es in Typescript auch möglich Mocking-Bibliotheken für Javascript, wie z.B. Sinon.JS, zu verwenden. Diese bieten jedoch in er Regel keine Typisierung der Mocks, was das Refactoring erschwert. Wenn z.B. eine Methode umbenannt wird, die in mehreren Tests gemockt wird, muss die Umbenennung der Methode in allen Tests manuell erfolgen. Aus diesem Grund ist es sinnvoll eine Mocking-Bibliothek zu verwenden, die mit typisierten Mocks arbeitet.

Wenn man auf npmjs.org nach den Stichworten Typescript und mock sucht, findet man einige Mocking-Bibliotheken speziell für Typescript. Zu den beliebtesten gehören die Bibliotheken TypeMoq und ts-mockito. Die folgende Grafik zeigt die wöchentlichen Downloadzahlen der beiden Bibliotheken im letzten Jahr sowie ein paar Statistiken zu den zugehörigen GitHub-Repositories. Die Anzahl an Downloads ist bei ts-mockito in den letzten Monaten etwas höher während TypeMoq ein wenig mehr Sterne auf GitHub hat.

Downloads der Bibliotheken TypeMoq und ts-mockito innerhalb eines Jahres

Abbildung 1: Downloads der Bibliotheken TypeMoq und ts-mockito innerhalb eines Jahres / Bildquelle: npmjs.org

Um die beiden Mocking-Bibliotheken vergleichen zu können, verwende ich das TodoService-Beispiel aus meinem letzten Blog-Artikel. Der Service hat die zwei Methoden getTodosCreatedByUser und markAsDone, die beide getestet werden sollen. Da der Service als Abhängigkeiten zwei weitere Services besitzt, sollen diese für die Tests gemockt werden. Der Quellcode für die folgenden Beispiele ist wieder auf GitHub unter den Branches ts-mockito bzw. typemoq zu finden.

ts-mockito

ts-mockito ist an die Mocking-Bibliothek Mockito für Java angelehnt, sodass die Syntax sehr ähnlich ist. Über die Funktion mock kann z.B. ein Mock für den TodoDataService erstellt werden. Obwohl der Rückgabewert bereits eine Instanz des TodoDataService ist, ist es anschließend notwendig über die instance-Funktion eine Objekt-Instanz des Mocks zu erstellen. Diese ist ebenfalls vom Typ TodoDataService und kann dann an den Service übergeben werden.

Abbildung 2: Mocking-Bibliotheken / Bildquelle: Christina Braun, generic.de AG

Um den Rückgabewert einer Methode zu mocken, wird der Aufruf when(…).thenReturn(…) verwendet. Dies funktioniert bei der Methode getTodos genauso wie beim Getter currentUser. Im Gegensatz zum Mocken mit Jest ist also für Getter kein Workaround erforderlich.

Abbildung 3: Mocking-Bibliotheken / Bildquelle: Christina Braun, generic.de AG

Zum Prüfen, ob die updateTodo-Methode mit dem erwarteten Parameter aufgerufen wurde, werden die Funktionen verify und called verwendet. Der erwartete Todo-Parameter muss dabei mithilfe von deepEqual verglichen werden. Da ansonsten nur ein Referenzvergleich durchgeführt wird.

Abbildung 4: Mocking-Bibliotheken / Bildquelle: Christina Braun, generic.de AG

TypeMog

Auch TypeMoq basiert mit der C#-Bibliothek Moq auf einer bekannten Mocking-Bibliothek. Die Mocks werden als IMock deklariert und über die Funktion Mock.ofType erstellt. Dem TodoService wird anschließend nicht das Mock-Objekt selbst sondern dessen Property object übergeben. Dabei handelt es sich um eine Instanz des gemockten Services. Im Gegensatz zu ts-mockito bietet TypeMoq auch die Möglichkeit, ein Mock-Objekt für ein Interface zu erstellen.

Abbildung 5: Mocking-Bibliotheken / Bildquelle: Christina Braun, generic.de AG

Zum Mocken des Rückgabewerts von getTodo, wird die Methode setup aufgerufen und anschließend mithilfe von returns der Rückgabewert definiert. Wie auch schon bei ts-mockito gibt es dabei keinen Unterschied in der Syntax beim Mocken von Methoden und Gettern.

Abbildung 6: Mocking-Bibliotheken / Bildquelle: Christina Braun, generic.de AG

Beim Überpüfen von Methodenaufrufen wird die verify-Methode des Mock-Objekts aufgerufen. Der zweite Parameter ist dabei vom Typ Times und prüft die Anzahl der Aufrufe. Neben once gibt es noch einige weitere Methoden, mit denen man z.B. prüfen kann, dass ein Aufruf mindestens einmal, höchstens einmal oder gar nicht erfolgt ist.

Abbildung 7: Mocking-Bibliotheken / Bildquelle: Christina Braun, generic.de AG

Fazit

Sowohl ts-mockito als auch TypeMoq unterstützen die zum Testen der Beispiel-Klasse benötigte Funktionalität. Mit beiden Bibliotheken lassen sich auf einfache Weise typisierte Mocks erstellen. TypeMoq bietet ein paar zusätzliche Features wie z.B. das Mocken von Interfaces. Wer diese zusätzliche Funktionalität jedoch nicht benötigt, kann anhand der Syntax entscheiden, welche Bibliothek ihm*ihr besser gefällt. Falls man Mockito oder Moq bereits kennt, wird die Entscheidung für eine der Bibliotheken aufgrund der vertrauten Syntax vermutlich leicht fallen.

Quellen

Abbildung 1: Statistik ts-mockito/typemoq: https://www.npmtrends.com/ts-mockito-vs-typemoq

https://www.npmjs.com/package/ts-mockito

https://www.npmjs.com/package/typemoq

13.12.2018 von Christina, generic.de AG