{"id":425,"date":"2024-06-03T22:04:33","date_gmt":"2024-06-03T21:04:33","guid":{"rendered":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=425"},"modified":"2024-06-26T22:08:11","modified_gmt":"2024-06-26T21:08:11","slug":"tests-fuer-http-clients-erstellen-mit-der-wiremock-java-library","status":"publish","type":"post","link":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=425","title":{"rendered":"Tests f\u00fcr HTTP-Clients erstellen mit der WireMock-Java-Library"},"content":{"rendered":"\n<p>In der modernen Softwareentwicklung ist das Testen ein wesentlicher Bestandteil des Entwicklungsprozesses. Tests stellen sicher, dass der Code wie erwartet funktioniert und erm\u00f6glichen eine kontinuierliche Integration und Bereitstellung. Ein h\u00e4ufiges Szenario beim Testen ist die Notwendigkeit, externe APIs zu simulieren, um die Abh\u00e4ngigkeiten zu isolieren und wiederholbare Tests durchzuf\u00fchren. Hier kommt WireMock ins Spiel.<\/p>\n\n\n\n<p>WireMock ist eine flexible und leistungsstarke Java-Bibliothek, die speziell entwickelt wurde, um HTTP-APIs zu simulieren. Mit WireMock k\u00f6nnen Entwickler Mock-Server erstellen, die HTTP-Anfragen entgegennehmen und vorher definierte Antworten zur\u00fcckgeben. Dies erm\u00f6glicht es, das Verhalten externer Dienste nachzubilden, ohne auf die tats\u00e4chlichen Dienste zugreifen zu m\u00fcssen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installation und Einrichtung<\/h2>\n\n\n\n<p>Um WireMock in einem Java-Projekt zu verwenden, m\u00fcssen die entsprechenden Abh\u00e4ngigkeiten in die Projektdatei eingef\u00fcgt werden. In einem Maven-Projekt f\u00fcgen wir folgende Dependency in die <code>pom.xml<\/code>-Datei ein:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>com.github.tomakehurst<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>wiremock-jre8<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>2.32.0<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">scope<\/span>&gt;<\/span>test<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">scope<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>F\u00fcr Gradle-Projekte wird die Dependency in die <code>build.gradle<\/code>-Datei eingef\u00fcgt:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">testImplementation <span class=\"hljs-string\">'com.github.tomakehurst:wiremock-jre8:2.32.0'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Nach dem Hinzuf\u00fcgen der Abh\u00e4ngigkeiten k\u00f6nnen wir mit der Verwendung von WireMock in unseren Tests beginnen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Grundlegende Verwendung<\/h2>\n\n\n\n<p>Um WireMock in einem Test zu verwenden, m\u00fcssen wir einen WireMock-Server starten, Anfragen und Antworten konfigurieren und den Server anschlie\u00dfend stoppen. Ein einfacher JUnit-Test mit WireMock k\u00f6nnte wie folgt aussehen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> com.github.tomakehurst.wiremock.WireMockServer;\n<span class=\"hljs-keyword\">import<\/span> com.github.tomakehurst.wiremock.client.WireMock;\n<span class=\"hljs-keyword\">import<\/span> com.github.tomakehurst.wiremock.core.WireMockConfiguration;\n<span class=\"hljs-keyword\">import<\/span> org.junit.jupiter.api.AfterEach;\n<span class=\"hljs-keyword\">import<\/span> org.junit.jupiter.api.BeforeEach;\n<span class=\"hljs-keyword\">import<\/span> org.junit.jupiter.api.Test;\n\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">static<\/span> com.github.tomakehurst.wiremock.client.WireMock.aResponse;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">static<\/span> com.github.tomakehurst.wiremock.client.WireMock.equalTo;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">static<\/span> com.github.tomakehurst.wiremock.client.WireMock.get;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">static<\/span> com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">static<\/span> org.junit.jupiter.api.Assertions.assertEquals;\n\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">WireMockTest<\/span> <\/span>{\n\n    private WireMockServer wireMockServer;\n\n    @BeforeEach\n    public <span class=\"hljs-keyword\">void<\/span> setup() {\n        wireMockServer = <span class=\"hljs-keyword\">new<\/span> WireMockServer(WireMockConfiguration.options().port(<span class=\"hljs-number\">8080<\/span>));\n        wireMockServer.start();\n        WireMock.configureFor(<span class=\"hljs-string\">\"localhost\"<\/span>, <span class=\"hljs-number\">8080<\/span>);\n    }\n\n    @AfterEach\n    public <span class=\"hljs-keyword\">void<\/span> teardown() {\n        wireMockServer.stop();\n    }\n\n    @Test\n    public <span class=\"hljs-keyword\">void<\/span> testGetEndpoint() {\n        wireMockServer.stubFor(<span class=\"hljs-keyword\">get<\/span>(urlEqualTo(\"\/api\/test\"))\n            .willReturn(aResponse()\n                .withStatus(200)\n                .withHeader(\"Content-Type\", \"application\/json\")\n                .withBody(\"{\\<span class=\"hljs-string\">\"message\\\":\\\"Hello, World!\\\"}\"<\/span>)));\n\n        <span class=\"hljs-comment\">\/\/ Hier w\u00fcrde der tats\u00e4chliche HTTP-Client auf den WireMock-Server zugreifen<\/span>\n        <span class=\"hljs-built_in\">String<\/span> response = sendHttpRequest(<span class=\"hljs-string\">\"http:\/\/localhost:8080\/api\/test\"<\/span>);\n\n        assertEquals(<span class=\"hljs-string\">\"{\\\"message\\\":\\\"Hello, World!\\\"}\"<\/span>, response);\n    }\n\n    private <span class=\"hljs-built_in\">String<\/span> sendHttpRequest(<span class=\"hljs-built_in\">String<\/span> url) {\n        <span class=\"hljs-comment\">\/\/ Methode zum Senden einer HTTP-Anfrage und R\u00fcckgabe der Antwort als String<\/span>\n        <span class=\"hljs-comment\">\/\/ Dies k\u00f6nnte beispielsweise mit HttpClient, RestTemplate oder einer anderen HTTP-Client-Bibliothek erfolgen<\/span>\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"\"<\/span>; <span class=\"hljs-comment\">\/\/ Dummy-R\u00fcckgabe f\u00fcr das Beispiel<\/span>\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Erkl\u00e4rung des Codes<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Setup und Teardown<\/strong>:\n<ul class=\"wp-block-list\">\n<li>In der <code>setup<\/code>-Methode wird ein WireMock-Server auf Port 8080 gestartet.<\/li>\n\n\n\n<li>Die <code>teardown<\/code>-Methode stoppt den Server nach jedem Test.<\/li>\n\n\n\n<li><code>WireMock.configureFor(\"localhost\", 8080)<\/code> konfiguriert WireMock, um auf Anfragen an <code>localhost:8080<\/code> zu reagieren.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Stubbing von Anfragen<\/strong>:\n<ul class=\"wp-block-list\">\n<li><code>wireMockServer.stubFor(get(urlEqualTo(\"\/api\/test\"))<\/code> definiert, dass eine GET-Anfrage an <code>\/api\/test<\/code> eine vorgegebene Antwort zur\u00fcckgibt.<\/li>\n\n\n\n<li><code>willReturn(aResponse().withStatus(200).withHeader(\"Content-Type\", \"application\/json\").withBody(\"{\\\"message\\\":\\\"Hello, World!\\\"}\"))<\/code> spezifiziert die Antwort, einschlie\u00dflich Statuscode, Header und Body.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Senden einer HTTP-Anfrage<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Die Methode <code>sendHttpRequest<\/code> simuliert das Senden einer HTTP-Anfrage. In einem realen Szenario w\u00fcrde dies durch eine HTTP-Client-Bibliothek wie <code>HttpClient<\/code> oder <code>RestTemplate<\/code> erfolgen.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Erweiterte Funktionen<\/h2>\n\n\n\n<p>WireMock bietet eine Vielzahl von erweiterten Funktionen, die \u00fcber einfache Stub-Anfragen hinausgehen. Dazu geh\u00f6ren:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Anfragen-Verifizierung<\/h3>\n\n\n\n<p>Neben dem Stubbing k\u00f6nnen wir auch \u00fcberpr\u00fcfen, ob bestimmte Anfragen w\u00e4hrend des Tests gesendet wurden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">@Test\n<span class=\"hljs-keyword\">public<\/span> void testRequestVerification() {\n    wireMockServer.stubFor(get(urlEqualTo(<span class=\"hljs-string\">\"\/api\/verify\"<\/span>))\n        .willReturn(aResponse().withStatus(<span class=\"hljs-number\">200<\/span>)));\n\n    sendHttpRequest(<span class=\"hljs-string\">\"http:\/\/localhost:8080\/api\/verify\"<\/span>);\n\n    WireMock.verify(WireMock.getRequestedFor(urlEqualTo(<span class=\"hljs-string\">\"\/api\/verify\"<\/span>)));\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Dynamische Antworten<\/h3>\n\n\n\n<p>WireMock unterst\u00fctzt auch dynamische Antworten, die auf den eingehenden Anfragen basieren:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">wireMockServer.stubFor(get(urlPathEqualTo(<span class=\"hljs-string\">\"\/api\/resource\"<\/span>))\n    .withQueryParam(<span class=\"hljs-string\">\"id\"<\/span>, equalTo(<span class=\"hljs-string\">\"123\"<\/span>))\n    .willReturn(aResponse()\n        .withStatus(<span class=\"hljs-number\">200<\/span>)\n        .withBody(<span class=\"hljs-string\">\"{\\\"resource\\\":\\\"123\\\"}\"<\/span>)));<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Simulieren von Verz\u00f6gerungen und Fehlern<\/h3>\n\n\n\n<p>Um Netzwerkbedingungen oder Fehler zu simulieren, kann WireMock Verz\u00f6gerungen und verschiedene Fehlerarten einf\u00fcgen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">wireMockServer.stubFor(get(urlEqualTo(<span class=\"hljs-string\">\"\/api\/timeout\"<\/span>))\n    .willReturn(aResponse()\n        .withFixedDelay(<span class=\"hljs-number\">3000<\/span>) <span class=\"hljs-comment\">\/\/ 3 Sekunden Verz\u00f6gerung<\/span>\n        .withStatus(<span class=\"hljs-number\">200<\/span>)\n        .withBody(<span class=\"hljs-string\">\"Delayed response\"<\/span>)));\n\nwireMockServer.stubFor(get(urlEqualTo(<span class=\"hljs-string\">\"\/api\/error\"<\/span>))\n    .willReturn(aResponse()\n        .withStatus(<span class=\"hljs-number\">500<\/span>) <span class=\"hljs-comment\">\/\/ Interner Serverfehler<\/span>\n        .withBody(<span class=\"hljs-string\">\"Internal Server Error\"<\/span>)));<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Verwendung in verschiedenen Testframeworks<\/h2>\n\n\n\n<p>WireMock l\u00e4sst sich nahtlos in verschiedene Testframeworks wie JUnit und TestNG integrieren. Hier ist ein Beispiel f\u00fcr die Verwendung mit JUnit 5:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> com.github.tomakehurst.wiremock.junit5.WireMockExtension;\n<span class=\"hljs-keyword\">import<\/span> org.junit.jupiter.api.extension.RegisterExtension;\n<span class=\"hljs-keyword\">import<\/span> org.junit.jupiter.api.Test;\n\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">static<\/span> com.github.tomakehurst.wiremock.client.WireMock.*;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">static<\/span> org.junit.jupiter.api.Assertions.assertEquals;\n\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">WireMockJUnit5Test<\/span> <\/span>{\n\n    @RegisterExtension\n    <span class=\"hljs-keyword\">static<\/span> WireMockExtension wireMockExtension = WireMockExtension.newInstance()\n        .options(WireMockConfiguration.wireMockConfig().port(<span class=\"hljs-number\">8080<\/span>))\n        .build();\n\n    @Test\n    public <span class=\"hljs-keyword\">void<\/span> testWithExtension() {\n        stubFor(<span class=\"hljs-keyword\">get<\/span>(urlEqualTo(\"\/api\/extension\"))\n            .willReturn(aResponse()\n                .withStatus(200)\n                .withBody(\"Hello from extension!\")));\n\n        String response = sendHttpRequest(\"http:\/\/localhost:8080\/api\/extension\");\n\n        assertEquals(\"Hello from extension!\", response);\n    }\n\n    private String sendHttpRequest(String url) {\n        <span class=\"hljs-comment\">\/\/ Methode zum Senden einer HTTP-Anfrage und R\u00fcckgabe der Antwort als String<\/span>\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"\"<\/span>; <span class=\"hljs-comment\">\/\/ Dummy-R\u00fcckgabe f\u00fcr das Beispiel<\/span>\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Fazit<\/h2>\n\n\n\n<p>WireMock ist ein unverzichtbares Werkzeug f\u00fcr Entwickler, die zuverl\u00e4ssige und wiederholbare Tests f\u00fcr ihre Anwendungen erstellen m\u00f6chten. Durch die M\u00f6glichkeit, externe HTTP-Dienste zu simulieren, k\u00f6nnen Tests isoliert und unabh\u00e4ngig von externen Systemen durchgef\u00fchrt werden. Dies f\u00fchrt zu stabileren und aussagekr\u00e4ftigeren Testergebnissen.<\/p>\n\n\n\n<p>Mit den vielf\u00e4ltigen Funktionen von WireMock, einschlie\u00dflich der M\u00f6glichkeit, Anfragen zu stubben, zu verifizieren und dynamische Antworten zu erstellen, bietet die Bibliothek eine umfassende L\u00f6sung f\u00fcr das Testen von HTTP-Clients und API-Integrationen. Ob in einfachen Unit-Tests oder komplexen Integrationstests, WireMock erleichtert das Testen und tr\u00e4gt zur Qualit\u00e4tssicherung in der Softwareentwicklung bei.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In der modernen Softwareentwicklung ist das Testen ein wesentlicher Bestandteil des Entwicklungsprozesses. Tests stellen sicher, dass der Code wie erwartet funktioniert und erm\u00f6glichen eine kontinuierliche Integration und Bereitstellung. Ein h\u00e4ufiges Szenario beim Testen ist die Notwendigkeit, externe APIs zu simulieren, um die Abh\u00e4ngigkeiten zu isolieren und wiederholbare Tests durchzuf\u00fchren. Hier kommt WireMock ins Spiel. WireMock [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-425","post","type-post","status-publish","format-standard","hentry","category-plain_java"],"_links":{"self":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/425","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=425"}],"version-history":[{"count":1,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/425\/revisions"}],"predecessor-version":[{"id":426,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/425\/revisions\/426"}],"wp:attachment":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=425"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=425"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=425"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}