CompletableFutureCarControllerIntegrationTest
authorGustavo Martin Morcuende <gu.martinm@gmail.com>
Sun, 11 Dec 2016 17:51:02 +0000 (18:51 +0100)
committerGustavo Martin Morcuende <gu.martinm@gmail.com>
Sun, 11 Dec 2016 17:51:02 +0000 (18:51 +0100)
SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/CompletableFutureCarController.java [new file with mode: 0644]
SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/DeferrableCarController.java [deleted file]
SpringJava/RxJava/web-services-spring-rxjava-server/src/test/java/de/spring/webservices/rest/controller/CompletableFutureCarControllerIntegrationTest.java [new file with mode: 0644]

diff --git a/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/CompletableFutureCarController.java b/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/CompletableFutureCarController.java
new file mode 100644 (file)
index 0000000..9b199f0
--- /dev/null
@@ -0,0 +1,105 @@
+package de.spring.webservices.rest.controller;
+
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import static de.spring.webservices.rest.controller.adapters.CompletableFutureAdapter.deferredAdapter;
+
+import javax.inject.Inject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.context.request.async.DeferredResult;
+
+import de.spring.webservices.domain.Car;
+import de.spring.webservices.rest.business.service.CompletableFutureBusinessLogic;
+
+@RestController
+@RequestMapping("/api/completablefuture/cars/")
+public class CompletableFutureCarController {
+       private static final Logger LOGGER = LoggerFactory.getLogger(CompletableFutureCarController.class);
+       private static final int PAGE = 2;
+       private static final int PAGE_SIZE = 10;
+       
+       private final CompletableFutureBusinessLogic completableFutureBusinessLogic;
+
+       @Inject
+    public CompletableFutureCarController(CompletableFutureBusinessLogic completableFutureBusinessLogic) {
+               this.completableFutureBusinessLogic = completableFutureBusinessLogic;
+       }
+
+       @RequestMapping(produces = { MediaType.APPLICATION_JSON_UTF8_VALUE }, method = RequestMethod.GET)
+    @ResponseStatus(HttpStatus.OK)
+    public DeferredResult<Page<Car>> cars() {
+                                       
+               return deferredAdapter(completableFutureBusinessLogic.findAll(new PageRequest(PAGE, PAGE_SIZE)));
+    }
+
+    @RequestMapping(value = "{id}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.GET)
+    @ResponseStatus(HttpStatus.OK)
+    public DeferredResult<Car> car(@RequestHeader(value = "MY_HEADER", required = false) String specialHeader,
+                       @PathVariable("id") long id,
+                       @RequestParam Map<String, String> params,
+                       @RequestParam(value = "wheel", required = false) String[] wheelParams) {
+               
+       if (specialHeader != null) {
+               LOGGER.info("SPECIAL HEADER: " + specialHeader);
+       }
+        
+       if (params.get("mirror") != null) {
+               LOGGER.info("MIRROR: " + params.get("mirror")); 
+       }
+       
+       if (params.get("window") != null) {
+               LOGGER.info("WINDOW: " + params.get("window"));
+       }
+       
+       if (wheelParams != null) {
+               for(String wheel : wheelParams) {
+                       LOGGER.info(wheel);
+               }
+       }
+               
+               return deferredAdapter(completableFutureBusinessLogic.findById(id));
+
+    }
+    
+    @RequestMapping(consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
+               produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.POST)
+       @ResponseStatus(HttpStatus.CREATED)
+    public DeferredResult<ResponseEntity<Car>> create(@RequestBody Car car) {
+       
+       return deferredAdapter(createAsync(car));
+    }
+
+    
+    private CompletableFuture<ResponseEntity<Car>> createAsync(Car car) {
+       
+       return completableFutureBusinessLogic
+                       .createThrowable(car)
+                       .thenComposeAsync(newCar -> 
+                               CompletableFuture.supplyAsync(() -> createResponseCar(newCar))
+               
+                       );              
+    }
+    
+    private ResponseEntity<Car> createResponseCar(Car car) {           
+               HttpHeaders headers = new HttpHeaders();
+           headers.add(HttpHeaders.LOCATION, "/api/completablefuture/cars/" + car.getId());
+           return new ResponseEntity<>(car, headers, HttpStatus.CREATED);
+    }
+}
diff --git a/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/DeferrableCarController.java b/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/DeferrableCarController.java
deleted file mode 100644 (file)
index caf35b4..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-package de.spring.webservices.rest.controller;
-
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-
-import static de.spring.webservices.rest.controller.adapters.CompletableFutureAdapter.deferredAdapter;
-
-import javax.inject.Inject;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestHeader;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.context.request.async.DeferredResult;
-
-import de.spring.webservices.domain.Car;
-import de.spring.webservices.rest.business.service.CompletableFutureBusinessLogic;
-
-@RestController
-@RequestMapping("/api/deferrable/cars/")
-public class DeferrableCarController {
-       private static final Logger LOGGER = LoggerFactory.getLogger(DeferrableCarController.class);
-       private static final int PAGE = 2;
-       private static final int PAGE_SIZE = 10;
-       
-       private final CompletableFutureBusinessLogic completableFutureBusinessLogic;
-
-       @Inject
-    public DeferrableCarController(CompletableFutureBusinessLogic completableFutureBusinessLogic) {
-               this.completableFutureBusinessLogic = completableFutureBusinessLogic;
-       }
-
-       @RequestMapping(produces = { MediaType.APPLICATION_JSON_UTF8_VALUE }, method = RequestMethod.GET)
-    @ResponseStatus(HttpStatus.OK)
-    public DeferredResult<Page<Car>> cars() {
-                                       
-               return deferredAdapter(completableFutureBusinessLogic.findAll(new PageRequest(PAGE, PAGE_SIZE)));
-    }
-
-    @RequestMapping(value = "{id}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.GET)
-    @ResponseStatus(HttpStatus.OK)
-    public DeferredResult<Car> car(@RequestHeader(value = "MY_HEADER", required = false) String specialHeader,
-                       @PathVariable("id") long id,
-                       @RequestParam Map<String, String> params,
-                       @RequestParam(value = "wheel", required = false) String[] wheelParams) {
-               
-       if (specialHeader != null) {
-               LOGGER.info("SPECIAL HEADER: " + specialHeader);
-       }
-        
-       if (params.get("mirror") != null) {
-               LOGGER.info("MIRROR: " + params.get("mirror")); 
-       }
-       
-       if (params.get("window") != null) {
-               LOGGER.info("WINDOW: " + params.get("window"));
-       }
-       
-       if (wheelParams != null) {
-               for(String wheel : wheelParams) {
-                       LOGGER.info(wheel);
-               }
-       }
-               
-               return deferredAdapter(completableFutureBusinessLogic.findById(id));
-
-    }
-    
-    @RequestMapping(consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
-               produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.POST)
-       @ResponseStatus(HttpStatus.CREATED)
-    public DeferredResult<ResponseEntity<Car>> create(@RequestBody Car car) {
-       
-       return deferredAdapter(createAsync(car));
-    }
-
-    
-    private CompletableFuture<ResponseEntity<Car>> createAsync(Car car) {
-       
-       return completableFutureBusinessLogic
-                       .createThrowable(car)
-                       .thenComposeAsync(newCar -> 
-                               CompletableFuture.supplyAsync(() -> createResponseCar(newCar))
-               
-                       );              
-    }
-    
-    private ResponseEntity<Car> createResponseCar(Car car) {           
-               HttpHeaders headers = new HttpHeaders();
-           headers.add(HttpHeaders.LOCATION, "/api/cars/" + car.getId());
-           return new ResponseEntity<>(car, headers, HttpStatus.CREATED);
-    }
-}
diff --git a/SpringJava/RxJava/web-services-spring-rxjava-server/src/test/java/de/spring/webservices/rest/controller/CompletableFutureCarControllerIntegrationTest.java b/SpringJava/RxJava/web-services-spring-rxjava-server/src/test/java/de/spring/webservices/rest/controller/CompletableFutureCarControllerIntegrationTest.java
new file mode 100644 (file)
index 0000000..8c41608
--- /dev/null
@@ -0,0 +1,128 @@
+package de.spring.webservices.rest.controller;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.Matchers.any;
+import static org.hamcrest.Matchers.is;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import de.spring.webservices.domain.Car;
+import de.spring.webservices.rest.business.service.CompletableFutureBusinessLogic;
+
+
+// jsonPath, how to: https://github.com/jayway/JsonPath | http://jsonpath.herokuapp.com/ 
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({ "classpath*:spring-configuration/mvc/rest/*.xml"})
+public class CompletableFutureCarControllerIntegrationTest {
+       private static final int PAGE = 2;
+       private static final int PAGE_SIZE = 10;
+       private static final String TEMPLATE = "Car: %s";
+       
+       private CompletableFutureBusinessLogic completableFutureBusinessLogic;
+       private CompletableFutureCarController controller;
+       private MockMvc mockMvc;
+       
+    @Before
+    public void setup() {
+       completableFutureBusinessLogic = mock(CompletableFutureBusinessLogic.class);
+       controller = new CompletableFutureCarController(completableFutureBusinessLogic);
+        mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
+    }
+
+       @Test
+       public void testWhenGetAllCarsThenRetrieveJsonValues() throws Exception {
+        final List<Car> cars = new ArrayList<>();
+        cars.add(new Car(1L, String.format(TEMPLATE, 1)));
+        CompletableFuture<Page<Car>> future = CompletableFuture.supplyAsync(() -> new PageImpl<>(cars));
+               given(completableFutureBusinessLogic.findAll(new PageRequest(PAGE, PAGE_SIZE))).willReturn(future);
+               
+               MvcResult result = mockMvc.perform(get("/api/completablefuture/cars/")
+                               .accept(MediaType.APPLICATION_JSON_UTF8))
+                               .andExpect(request().asyncStarted())
+                               .andExpect(request().asyncResult(instanceOf(Page.class)))
+                               .andReturn();
+               
+                mockMvc.perform(asyncDispatch(result))
+               .andExpect(status().isOk())
+               .andExpect(jsonPath("$.content[0].id", any(Integer.class)))
+               .andExpect(jsonPath("$.content[0].id", any(Integer.class)))
+               .andExpect(jsonPath("$.content[0].content", is("Car: 1")))
+               .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8));
+       }
+       
+       @Test
+       public void testWhenGetOneCarThenRetrieveJsonValue() throws Exception {
+               CompletableFuture<Car> expected = CompletableFuture.supplyAsync(() -> new Car(1L, String.format(TEMPLATE, 1)));
+               given(completableFutureBusinessLogic.findById(1L)).willReturn(expected);
+
+               MvcResult result = mockMvc.perform(get("/api/completablefuture/cars/{id}", 1L)
+                               .accept(MediaType.APPLICATION_JSON_UTF8))
+                               .andExpect(request().asyncStarted())
+                               .andExpect(request().asyncResult(instanceOf(Car.class)))
+                               .andReturn();
+       
+                mockMvc.perform(asyncDispatch(result))
+               .andExpect(status().isOk())
+               .andExpect(jsonPath("id", any(Integer.class)))
+               .andExpect(jsonPath("content", is("Car: 1")))
+               .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8));
+       }
+       
+       @Test
+       public void testWhenCreateNewCarThenRetrieveJsonValue() throws Exception {
+               Car car = new Car(null, "nothing");
+               CompletableFuture<Car> expected = CompletableFuture.supplyAsync(() -> new Car(1L, String.format(TEMPLATE, 1)));
+               given(completableFutureBusinessLogic.createThrowable(car)).willReturn(expected);
+
+               MvcResult result = mockMvc.perform(post("/api/completablefuture/cars/")
+                               .contentType(MediaType.APPLICATION_JSON_UTF8)
+                               .content(asJsonString(car))
+                               .accept(MediaType.APPLICATION_JSON_UTF8))
+                               .andExpect(request().asyncStarted())
+                               .andExpect(request().asyncResult(instanceOf(ResponseEntity.class)))
+                               .andReturn();
+               
+               mockMvc.perform(asyncDispatch(result))
+               .andExpect(status().isCreated())
+               .andExpect(jsonPath("id", any(Integer.class)))
+               .andExpect(jsonPath("content", is("Car: 1")))
+               .andExpect(header().string(HttpHeaders.LOCATION, "/api/completablefuture/cars/1"))
+               .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8));
+       }
+       
+       private static String asJsonString(final Object obj) throws JsonProcessingException {
+               final ObjectMapper mapper = new ObjectMapper();
+               return mapper.writeValueAsString(obj);
+       }
+}