diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml
index c5ebb4116a..a2c4b3509f 100644
--- a/spring-cloud/pom.xml
+++ b/spring-cloud/pom.xml
@@ -46,7 +46,7 @@
spring-cloud-circuit-breaker
spring-cloud-eureka-self-preservation
-
+ spring-cloud-netflix-feign
spring-cloud-sentinel
spring-cloud-dapr
spring-cloud-docker
diff --git a/spring-cloud/spring-cloud-netflix-feign/pom.xml b/spring-cloud/spring-cloud-netflix-feign/pom.xml
index 8ff09d3070..f519b6316b 100644
--- a/spring-cloud/spring-cloud-netflix-feign/pom.xml
+++ b/spring-cloud/spring-cloud-netflix-feign/pom.xml
@@ -51,13 +51,16 @@
spring-boot-starter-test
test
+
+ org.springframework.cloud
+ spring-cloud-contract-wiremock
+ test
+
Camden.SR7
8.18.0
-
-
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/client/JSONPlaceHolderClient.java b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/client/JSONPlaceHolderClient.java
index 80a455a4c4..454caab38c 100644
--- a/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/client/JSONPlaceHolderClient.java
+++ b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/client/JSONPlaceHolderClient.java
@@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
@FeignClient(value = "jplaceholder",
- url = "https://jsonplaceholder.typicode.com/",
+ url = "${external.api.url}",
configuration = ClientConfiguration.class,
fallback = JSONPlaceHolderFallback.class)
public interface JSONPlaceHolderClient {
@@ -19,7 +19,7 @@ public interface JSONPlaceHolderClient {
@RequestMapping(method = RequestMethod.GET, value = "/posts")
List getPosts();
-
@RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json")
Post getPostById(@PathVariable("postId") Long postId);
+
}
diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/resources/application.properties b/spring-cloud/spring-cloud-netflix-feign/src/main/resources/application.properties
index 5927ccb9c1..a8a29dcdd5 100644
--- a/spring-cloud/spring-cloud-netflix-feign/src/main/resources/application.properties
+++ b/spring-cloud/spring-cloud-netflix-feign/src/main/resources/application.properties
@@ -1,3 +1,5 @@
spring.application.name=netflix-feign
logging.level.com.baeldung.cloud.netflix.feign.client=DEBUG
feign.hystrix.enabled=true
+
+external.api.url=https://jsonplaceholder.typicode.com/
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/ExampleTestApplication.java b/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/ExampleTestApplication.java
deleted file mode 100644
index f3c8459f87..0000000000
--- a/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/ExampleTestApplication.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.baeldung.cloud.netflix.feign;
-
-import com.baeldung.cloud.netflix.feign.config.ClientConfiguration;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringRunner;
-
-@RunWith(SpringRunner.class)
-@SpringBootTest
-@EnableAutoConfiguration
-@ContextConfiguration(classes = { ClientConfiguration.class })
-public class ExampleTestApplication {
-
- @Test
- public void whenSpringContextIsBootstrapped_thenNoExceptions() {
- }
-}
diff --git a/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/NetflixFeignUnitTest.java b/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/NetflixFeignUnitTest.java
index 880948d6d1..9ee925201d 100644
--- a/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/NetflixFeignUnitTest.java
+++ b/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/NetflixFeignUnitTest.java
@@ -2,42 +2,97 @@ package com.baeldung.cloud.netflix.feign;
import com.baeldung.cloud.netflix.feign.model.Post;
import com.baeldung.cloud.netflix.feign.service.JSONPlaceHolderService;
+import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.github.tomakehurst.wiremock.verification.LoggedRequest;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
-import static org.junit.Assert.assertFalse;
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.exactly;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.verify;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
@RunWith(SpringRunner.class)
-@SpringBootTest
+@SpringBootTest(properties = {"external.api.url=http://localhost:${wiremock.server.port}"})
+@AutoConfigureWireMock(port = 0)
public class NetflixFeignUnitTest {
@Autowired
private JSONPlaceHolderService jsonPlaceHolderService;
- @Test
- public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ @Before
+ public void setup() {
+ WireMock.reset();
}
@Test
- public void whenGetPosts_thenListPostSizeGreaterThanZero() {
+ public void givenExternalApiAvailable_whenGetPosts_thenPostsReturned() {
+
+ WireMock.stubFor(get(urlEqualTo("/posts"))
+ .willReturn(okJson("[{ \"userId\": 1, \"id\": 1, \"title\": \"post 1 title\", \"body\": \"post 1 body\" }, "
+ + "{ \"userId\": 1, \"id\": 2, \"title\": \"post 2 title\", \"body\": \"post 2 body\" }]")));
List posts = jsonPlaceHolderService.getPosts();
- assertFalse(posts.isEmpty());
+ assertEquals(2, posts.size());
+ verify(exactly(1), getRequestedFor(urlEqualTo("/posts")));
}
@Test
- public void whenGetPostWithId_thenPostExist() {
+ public void givenExternalApiUnavailable_whenGetPosts_thenEmpty() {
+
+ WireMock.stubFor(get(urlEqualTo("/posts"))
+ .willReturn(aResponse().withStatus(500)));
+
+ List posts = jsonPlaceHolderService.getPosts();
+
+ assertTrue(posts.isEmpty());
+ verify(exactly(1), getRequestedFor(urlEqualTo("/posts")));
+ }
+
+ @Test
+ public void givenExternalApiAvailable_whenGetPostWithId_thenPostExists() {
+
+ WireMock.stubFor(get(urlEqualTo("/posts/1"))
+ .willReturn(okJson("{ \"userId\": 1, \"id\": 1, \"title\": \"post 1 title\", \"body\": \"post 1 body\" }")));
Post post = jsonPlaceHolderService.getPostById(1L);
assertNotNull(post);
+ verify(exactly(1), getRequestedFor(urlEqualTo("/posts/1")));
}
+ @Test
+ public void givenExternalApiUnavailable_whenGetPostWithId_thenNull() {
+
+ WireMock.stubFor(get(urlEqualTo("/posts/1"))
+ .willReturn(aResponse().withStatus(500)));
+
+ Post post = jsonPlaceHolderService.getPostById(1L);
+
+ assertNull(post);
+ verify(exactly(1), getRequestedFor(urlEqualTo("/posts/1")));
+ }
+
+ private static ResponseDefinitionBuilder okJson(String json) {
+ return aResponse()
+ .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+ .withBody(json);
+ }
}