BAEL-3324 | Using JSON Patch in Spring REST APIs

This commit is contained in:
ramprasad.devarakonda@gmail.com
2020-02-08 23:58:31 +00:00
parent 8dd58252de
commit 9da15e9d94
13 changed files with 534 additions and 0 deletions
@@ -0,0 +1,17 @@
package com.baeldung.service.impl;
import com.baeldung.service.CustomerIdGenerator;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class CustomerIdGeneratorImplUnitTest {
@Test
public void givenIdGeneratedPreviously_whenGenerated_thenIdIsIncremented(){
CustomerIdGenerator customerIdGenerator = new CustomerIdGeneratorImpl();
int firstId = customerIdGenerator.generateNextId();
assertThat(customerIdGenerator.generateNextId()).isEqualTo(++firstId);
}
}
@@ -0,0 +1,94 @@
package com.baeldung.service.impl;
import com.baeldung.model.Customer;
import com.baeldung.service.CustomerIdGenerator;
import com.baeldung.service.CustomerService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.HashMap;
import java.util.Map;
import static com.baeldung.model.Customer.fromCustomer;
import static java.util.Arrays.asList;
import static java.util.Optional.empty;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
@RunWith(MockitoJUnitRunner.class)
public class CustomerServiceImplUnitTest {
@Mock
private CustomerIdGenerator mockCustomerIdGenerator;
private CustomerService customerService;
@Before
public void setup() {
customerService = new CustomerServiceImpl(mockCustomerIdGenerator);
}
@Test
public void whenCustomerIsCreated_thenNewCustomerDetailsAreCorrect() {
Map<String, Boolean> communicationPreferences = new HashMap<>();
communicationPreferences.put("post", true);
communicationPreferences.put("email", true);
Customer customer = new Customer("001-555-1234", asList("Milk", "Eggs"), communicationPreferences);
given(mockCustomerIdGenerator.generateNextId()).willReturn(1);
Customer newCustomer = customerService.createCustomer(customer);
assertThat(newCustomer.getId()).isEqualTo("1");
assertThat(newCustomer.getTelephone()).isEqualTo("001-555-1234");
assertThat(newCustomer.getFavorites()).containsExactly("Milk", "Eggs");
assertThat(newCustomer.getCommunicationPreferences()).isEqualTo(communicationPreferences);
}
@Test
public void givenNonExistentCustomer_whenCustomerIsLookedUp_thenCustomerCanNotBeFound() {
assertThat(customerService.findCustomer("CUST12345")).isEqualTo(empty());
}
@Test
public void whenCustomerIsCreated_thenCustomerCanBeFound() {
Map<String, Boolean> communicationPreferences = new HashMap<>();
communicationPreferences.put("post", true);
communicationPreferences.put("email", true);
Customer customer = new Customer("001-555-1234", asList("Milk", "Eggs"), communicationPreferences);
given(mockCustomerIdGenerator.generateNextId()).willReturn(7890);
customerService.createCustomer(customer);
Customer lookedUpCustomer = customerService.findCustomer("7890").get();
assertThat(lookedUpCustomer.getId()).isEqualTo("7890");
assertThat(lookedUpCustomer.getTelephone()).isEqualTo("001-555-1234");
assertThat(lookedUpCustomer.getFavorites()).containsExactly("Milk", "Eggs");
assertThat(lookedUpCustomer.getCommunicationPreferences()).isEqualTo(communicationPreferences);
}
@Test
public void whenCustomerUpdated_thenDetailsUpdatedCorrectly() {
given(mockCustomerIdGenerator.generateNextId()).willReturn(7890);
Map<String, Boolean> communicationPreferences = new HashMap<>();
communicationPreferences.put("post", true);
communicationPreferences.put("email", true);
Customer customer = new Customer("001-555-1234", asList("Milk", "Eggs"), communicationPreferences);
Customer newCustomer = customerService.createCustomer(customer);
Customer customerWithUpdates = fromCustomer(newCustomer);
customerWithUpdates.setTelephone("001-555-6789");
customerService.updateCustomer(customerWithUpdates);
Customer lookedUpCustomer = customerService.findCustomer("7890").get();
assertThat(lookedUpCustomer.getId()).isEqualTo("7890");
assertThat(lookedUpCustomer.getTelephone()).isEqualTo("001-555-6789");
assertThat(lookedUpCustomer.getFavorites()).containsExactly("Milk", "Eggs");
assertThat(lookedUpCustomer.getCommunicationPreferences()).isEqualTo(communicationPreferences);
}
}
@@ -0,0 +1,72 @@
package com.baeldung.web.controller;
import com.baeldung.model.Customer;
import com.baeldung.service.CustomerService;
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.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import static java.util.Collections.emptyList;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CustomerRestControllerIntegrationTest {
@Autowired
private CustomerService customerService;
@Autowired
private TestRestTemplate testRestTemplate;
@Before
public void setup() {
testRestTemplate.getRestTemplate().setRequestFactory(new HttpComponentsClientHttpRequestFactory());
}
@Test
public void givenExistingCustomer_whenPatched_thenOnlyPatchedFieldsUpdated() {
Map<String, Boolean> communicationPreferences = new HashMap<>();
communicationPreferences.put("post", true);
communicationPreferences.put("email", true);
Customer newCustomer = new Customer("001-555-1234", Arrays.asList("Milk", "Eggs"),
communicationPreferences);
Customer customer = customerService.createCustomer(newCustomer);
String patchBody = "[ { \"op\": \"replace\", \"path\": \"/telephone\", \"value\": \"001-555-5678\" },\n"
+ "{\"op\": \"add\", \"path\": \"/favorites/0\", \"value\": \"Bread\" }]";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf("application/json-patch+json"));
ResponseEntity<Customer> patchResponse
= testRestTemplate.exchange("/customers/{id}",
HttpMethod.PATCH,
new HttpEntity<>(patchBody, headers),
Customer.class,
customer.getId());
Customer customerPatched = patchResponse.getBody();
assertThat(patchResponse.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(customerPatched.getId()).isEqualTo(customer.getId());
assertThat(customerPatched.getTelephone()).isEqualTo("001-555-5678");
assertThat(customerPatched.getCommunicationPreferences().get("post")).isTrue();
assertThat(customerPatched.getCommunicationPreferences().get("email")).isTrue();
assertThat(customerPatched.getFavorites()).containsExactly("Bread", "Milk", "Eggs");
}
}
@@ -0,0 +1,101 @@
package com.baeldung.web.controller;
import com.baeldung.model.Customer;
import com.baeldung.service.CustomerService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import java.util.HashMap;
import java.util.Map;
import static java.util.Arrays.asList;
import static java.util.Optional.empty;
import static java.util.Optional.of;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern;
import static org.springframework.http.MediaType.APPLICATION_JSON;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class CustomerRestControllerUnitTest {
private static final String APPLICATION_JSON_PATCH_JSON = "application/json-patch+json";
@Autowired
private MockMvc mvc;
@MockBean
private CustomerService mockCustomerService;
@Autowired
ApplicationContext context;
@Test
public void whenCustomerCreated_then201ReturnedWithNewCustomerLocation() throws Exception {
Map<String, Boolean> communicationPreferences = new HashMap<>();
communicationPreferences.put("post", true);
communicationPreferences.put("email", true);
Customer customer = new Customer("001-555-1234", asList("Milk", "Eggs"), communicationPreferences);
Customer persistedCustomer = Customer.fromCustomer(customer);
persistedCustomer.setId("1");
given(mockCustomerService.createCustomer(customer)).willReturn(persistedCustomer);
String createCustomerRequestBody = "{"
+ "\"telephone\": \"001-555-1234\",\n"
+ "\"favorites\": [\"Milk\", \"Eggs\"],\n"
+ "\"communicationPreferences\": {\"post\":true, \"email\":true}\n"
+ "}";
mvc.perform(post("/customers")
.contentType(APPLICATION_JSON)
.content(createCustomerRequestBody))
.andExpect(status().isCreated())
.andExpect(redirectedUrlPattern("http://*/customers/1"));
}
@Test
public void givenNonExistentCustomer_whenPatched_then404Returned() throws Exception {
given(mockCustomerService.findCustomer("1")).willReturn(empty());
String patchInstructions = "[{\"op\":\"replace\",\"path\": \"/telephone\",\"value\":\"001-555-5678\"}]";
mvc.perform(patch("/customers/1")
.contentType(APPLICATION_JSON_PATCH_JSON)
.content(patchInstructions))
.andExpect(status().isNotFound());
}
@Test
public void givenExistingCustomer_whenPatched_thenReturnPatchedCustomer() throws Exception {
Map<String, Boolean> communicationPreferences = new HashMap<>();
communicationPreferences.put("post", true);
communicationPreferences.put("email", true);
Customer customer = new Customer("1", "001-555-1234", asList("Milk", "Eggs"), communicationPreferences);
given(mockCustomerService.findCustomer("1")).willReturn(of(customer));
String patchInstructions = "[{\"op\":\"replace\",\"path\": \"/telephone\",\"value\":\"001-555-5678\"}]";
mvc.perform(patch("/customers/1")
.contentType(APPLICATION_JSON_PATCH_JSON)
.content(patchInstructions))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id", is("1")))
.andExpect(jsonPath("$.telephone", is("001-555-5678")))
.andExpect(jsonPath("$.favorites", is(asList("Milk", "Eggs"))))
.andExpect(jsonPath("$.communicationPreferences", is(communicationPreferences)));
}
}