Beliebte Suchanfragen

Cloud Native

DevOps

IT-Security

Agile Methoden

Java

|
//

Mock Server betreiben mit Mountebank und Docker

31.5.2015 | 5 Minuten Lesezeit

Bei der Entwicklung von Applikationen die von anderen Systemen abhängig sind, z.B. durch die Anbindung von Geschäftslogik und Daten, steht man vor der Frage, wie diese getestet werden sollen, falls die Systeme nicht verfügbar sind. Klassischerweise würde diese Anbindung über Mocks in Unit- oder funktionalen Tests durchgeführt werden. Trotzdem kann auf dem Weg durch die Applikation bis zur Netzwerkschicht einiges schief gehen.

In diesem Artikel betrachten wir eine Lösung, die einen Mock Server für solche allumfassenden Tests bereitstellt. Auf diese Art können Aufrufe durch eine Applikation gegen einen Mock Server durchgeführt und tiefgreifend getestet werden. Dadurch werden allumfassende Applikation und System-Ende-zu-Ende-Tests ermöglicht.

Mountebank

Mountebank ist ein Open Source Tool, das plattformunabhängige Multi-Protokoll Test Doubletten auf der Netzwerkschicht bereitstellt [1 ]. Eine zu testende Applikation muss nur auf die IP oder URL der Mountebank Instanz verweisen, statt auf die reale Abhängigkeit. Das ermöglicht, die Applikation durch alle Applikationsschichten zu testen, wie man es sonst traditionell mit Stubs und Mocks tun würde. Unterstützte Protkolle sind HTTP, HTTPS, TCP und SMTP.

Zu diesem Zweck steht eine DSL bereit, die genutzt werden kann, um Imposter Stubs zu konfigurieren, welche statisch oder dynamisch Responses für Requests erstellen [2 ]. Diese Stub-Funktionalität ist mit einem Proxy Mode erweiterbar, der Aufrufe zu den Originalsystemen aufnehmen und abspielen kann [3 ], und einem Mock Verfikationssystem, das eine Verfikation von Anfragen zu asynchronen Aufrufen an den Mock Server ermöglicht [4 ].

In den meisten Fällen reicht ein einfacher Request Response Mock Stub. Solch eine Definition könnte wie folgt aussehen, z.B. für einen HTTP Mock:

1{
2  "port": 8010,
3  "protocol": "http",
4  "name": "My Mock",
5  "mode": "text",
6  "stubs": [
7    {
8      "responses": [
9        {
10          headers: {
11            'Content-Type': 'text/xml'
12          },
13          body: "..."
14        }
15      ],
16      "predicates": [
17        {
18          "and": [
19            {
20              "equals": {
21                "path": "/MyService/MyOperation"
22              }
23            },
24            {
25              "contains": {
26                "body": "Mountebank"
27              }
28            }
29          ]
30        }
31      ]
32    }
33  ]
34}

Der Stub würde am Port 8010 auf einen HTTP Call warten. Wenn die Prädikate zutreffen, in diesem Fall ein Aufruf von /MyService/MyOperation welches den String „Mountebank“ im POST Body enthalten würde, wird eine HTTP Response mit dem HTTP Content-Type „text/xml“ und dem Body „…“ gesendet.

Diese Definition kann an Mountebank entweder über das UI, das von Port 2525 erreichbar ist, über die REST API oder während des Applikationsstarts übergeben werden.

Mockdaten-Dateistruktur

Wenn die Applikation gestartet wird, kann eine Konfigurationsdatei automatisch an die Mountebank Instanz über die REST API gesendet werden.

Da solch eine Mockdaten-Datei viele verschiedene Stubs enthalten und dementsprechend groß und kompliziert werden kann, ist eine Vereinfachung notwendig. Diese ist möglich durch die Integration von JavaScript EJS Templating. Es kann verwendet werden, um eine größeren Mock-Datensatz bestehend aus mehreren Dateien und verschiedenen Ordern zu erstellen.

Die Hauptdatei „imposters.ejs“, die eine Liste für den Import von Mock Unterordnern für solch einen großen Mock Datensatz enthalten würde, könnte wie folgt aussehen:

1{
2  "port": 8010,
3  "protocol": "http",
4  "name": "NKD Mock",
5  "mode": "text",
6  "stubs": [
7    <% include myServiceA/imposters.ejs %>,
8    ...
9  ]
10}

Dabei würde im Unterordner die Datei „myServiceA/imposters.ejs“, welche die Stubs und Responses definiert, abgelegt werden. Zur weiteren Reduktion der Komplexität können diese wieder in separate Dateien ausgelagert werden:

1{
2  "responses": [
3    {
4      "inject": "<%- stringify(filename, 'myServiceA/responseA.ejs') %>"
5    }
6  ],
7  "predicates": [
8    {
9      "and": [
10        {
11          "equals": {
12            "path": "/MyService/MyOperation"
13          }
14        },
15        {
16          "contains": {
17            "body": "Mountebank"
18          }
19        }
20      ]
21    }
22  ]
23},
24{
25  "responses": [
26    {
27      "inject": "<%- stringify(filename, 'myServiceA/default.ejs') %>"
28    }
29  ],
30  "predicates": [
31    {
32      "equals": {
33        "path": "/MyService/MyOperation"
34      }
35    }
36  ]
37}

In diesem Fall haben wir außerdem einen Standardfall, der greift, falls die anderen Prädikate nicht erfolreich evaluiert werden.

Die Response wird als Json-Objekt von eine JavaScript-Funktion aus der Reponse-Datei „myServiceA/default.ejs“ zurück gegeben:

1function() {
2  return {
3    headers: {
4    'Content-Type': 'text/xml'
5  },
6    body: "..."
7  };
8}

Docker

Docker ist eine Open-Source-Technologie, die Virtualisierung von Maschinen in isolierten Containern auf einem Betriebssystem ermöglicht. Durch die Verwendung von Linux-Technologien wie Cgroups und Namespaces erlaubt es das schnelle und Ressourcen effiziente Erzeugen von Virtuellen Maschinen, womit man eine portable, nachvollziehbare und konsistente Infrastruktur aufbauen kann. Dies ist vor allem für die Erstellung, Durchführung und Nachvollziehbarkeit von Test-Szenarien, die infrastrukturbasiert sind, ein großer Vorteil.

Bauen des Mock Servers

Um ein Docker Image für dieses Szenario zu bauen, das die Mock Daten des Mock Servers bereits enthält, benutzen wir ein Docker Image, das Mountebank vorinstalliert hat und im Docker Repository verfügbar ist. Unsere Dockerfile würde wie folgt aussehen:

1FROM                    cpoepke/mountebank-basis:latest
2 
3ADD resources/imposters /mb/
4RUN ln -s /usr/bin/nodejs /usr/bin/node
5 
6EXPOSE 2525
7EXPOSE 8010
8 
9CMD mb --configfile /mb/imposters.ejs --allowInjection

Beim Bauen des Docker Images werden die Mock Daten aus dem Ordner „resources/imposters“ in den „/mb“ Ordner des Docker Images kopiert, die Mountebank Ports der VM freigeschaltet und ein Start Kommando bereitgestellt, das beim Start des Containers Mountebank mit den Mock Daten startet.

Das Docker Image selber wird auf die übliche Weise gebaut:

1build --tag="my-ws-mock" .

Starten des Mock Servers

Um den Mock Server mit bereits zugewiesen Ports zu starten, muss man folgendes Kommando ausführen:

1run -t -i -p 2525:2525 -p 8010:8010 --name='my-ws-mock' my-ws-mock

Anmerkung: Bitte vergessen Sie nicht, das VM Port Fowarding auf Mac und Windows für boot2docker!

Weiterführende Arbeiten

Weitere Arbeiten können durch die Integration des Build-Prozesses für dieses Docker Image und das Deployment des Artefakts in ein Repository oder durch eine Continuous Integration/Continuous Deployment Pipeline durchgeführt werden. Daraufhin kann der Mock Server in automatisierten Integrations-, Akzeptanz-, Smoke- oder System-Ende-zu-Ende-Tests verwendet werden, abhängig von der Teststrategie. Sogar größere Szenarien mit verschiedene Mock Servern sind möglich, um verteilte Systeme wie z.B. Microservice basierte Architekturen zu testen, in denen die Mock Server während der Initialisierung der Infrastruktur gestartet werden.

Fazit

In diesem Artikel, haben wir gezeigt, wie ein externer Mock Server mit einem großen Mock Datensatz erstellt werden kann. Dieser Mock Server kann paketiert werden, durch die Verwendung einer Container Technologie wie Docker, und zusätzlich in eine Continuous Integration/Continuous Deployment Pipeline integriert werden. Dies ermöglicht das tiefgreifende Testen einer Applikation durch ihre Schichten bis hin zur Netwerk Schicht hindurch.

Referenzen

[ 1] http://www.mbtest.org
[ 2] http://www.mbtest.org/docs/api/stubs
[ 3] http://www.mulesoft.org/documentation/display/current/Unit+Testing
[ 4] http://www.mbtest.org/docs/api/mocks
[ 5] https://www.docker.com/whatisdocker/

|

Beitrag teilen

Gefällt mir

0

//

Weitere Artikel in diesem Themenbereich

Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.

//

Gemeinsam bessere Projekte umsetzen.

Wir helfen deinem Unternehmen.

Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.

Hilf uns, noch besser zu werden.

Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.