Von Maik Krawinkel auf Dienstag, 27. August 2019
Kategorie: Application Development

Angular Unit-Tests: Einen HTTP-Request mocken

Dieser Blog-Post ist der Beginn einer Serie an Blog-Posts. In meinem aktuellen Projekt entwickle ich eine mittlerweile recht umfangreiche Angular Anwendung. Professionelle Softwareentwicklung ist ohne entsprechende (automatisierte) Tests gar nicht möglich. Von daher veröffentliche ich einige Posts rund um das Thema automatisierter Tests in nächster Zeit.

Starten möchte ich mit einfachen Unit-Tests. Getestet werden sollen Services die Requests per http an Rest-Schnittstellen schicken. Denn hier stellt sich die Frage, wie man den Test so schreibt, „als ob" eine echte Rest-Schnittstelle kontaktiert wurde und entsprechend antwortet. Denn genau das soll nicht stattfinden. Man muss sich also darum kümmern, dass beim Absenden des Requests eine Fake-Antwort generiert wird. Diese Fake-Daten werden auch als Mocks bezeichnet.

Das fertigen Quellcode kann man sich auf GitHub anschauen. Einfach auschecken und die Tests starten. So hat man gleich ein lauffähiges Beispiel!

Der Umfang des Projektes ist schnell erklärt. Die Anwendung zeigt eine Komponente „TodoComponent" an. Diese lädt über den „TodoService" ein JSON-Objekt. Dieser beinhaltet einen einzelnen Eintrag aus einer Aufgabenliste. Dieser Eintrag wird dann angezeigt.

Den „TodoService" schauen wir uns nun genauer an.

Wie Eingangs erwähnt möchte ich nun verdeutlichen, wie wir für diesen Service passende Unit-Tests schreiben. Die angular-cli hat bei der Erzeugung des Services eine passende Datei für die Tests angelegt. Es folgt die vollständige „todo.service.spec.ts" Datei.

Das Mocken eines http-Requests wollen wir uns im Folgenden näher anschauen.

Zuerst definieren wir uns ein Objekt, dass unsere nichtexistierende Rest-Schnitstelle zurückliefern soll. Der Attributname ist „mockResponse".

Natürlich muss die zu testende Methode „getTodo" aufgerufen werden. Da diese Methode ein Observable zurückliefert, ist ein „subscribe" erforderlich. Dadurch haben wir die Möglichkeit die gemockte Antwort der Schnittstelle auf Korrektheit zu überprüfen. Da der Service nicht einfach das gemockte JSON zurückliefert, können wir hier zum Beispiel schauen, ob die Transformierung fehlerfrei erfolgt ist. Durch das „subscribe" ist der Request abgeschickt. Allerdings wird kein echter http-Request abgeschickt, sondern der „HttpTestingController" kümmert sich darum, dass eine gemockte Antwort geliefert wird.

Wir müssen also veranlassen, dass auf den Request geantwortet wird. Wir sagen dem Objekt der Klasse „HttpTestingController", dass ein Request mit der angegeben URL abgeschickt worden sein muss. Dies ist ja durch das „subscribe" an dem Rückgabewert der „getTodo" Methode erfolgt. Es findet also eine Überprüfung statt, ob der Request an die erwartete URL geschickt wurde.

Zu guter Letzt wird der Request mit der „flush" Methode beantwortet. Der oben beschriebene „subscribe"-Block wird ausgeführt und die „expect"-Angaben werden überprüft.

Eine wichtige Sache fehlt noch. Im Kopf der Test-Definition befindet sich die Angabe „done: DoneFn". Ist diese Angabe vorhanden, muss die „done()"-Methode innerhalb unseres Tests aufgerufen werden. Ansonsten schlägt der Test fehl. Den Methodenaufruf packen wir in den „subscribe"-Block. Nun wird garantiert, dass das Observable auch wirklich beantwortet wird und somit die „expect"-Angaben im „subscribe"-Block wirklich ausgeführt wurden.

That's it! Es gibt also Unit-Tests, die folgende Dinge überprüfen:

Durch die beschriebe Vorgehensweise haben wir noch viele weitere Möglichkeiten unsere http-Requests zu überprüfen! Zum Beispiel wurde bisher der http-Status-Code noch nicht überprüft. Aber auch die Angabe von http-Headern oder die korrekte Übertragung von Authentifizierungsinformationen könnte überprüft werden.

Das und viele andere Dinge möchte ich gerne in nachfolgenden Blog-Posts näher erläutern. Nun könnt ihr euch das GitHub Repository auschecken und selber ausprobieren. Viel Spaß und Erfolg!

Kommentare hinterlassen