diff --git a/spring-rest-http/pom.xml b/spring-rest-http/pom.xml
index c5c6b8d44c..32d2804220 100644
--- a/spring-rest-http/pom.xml
+++ b/spring-rest-http/pom.xml
@@ -41,12 +41,18 @@
org.springframework.boot
spring-boot-starter-test
+
+ com.github.java-json-tools
+ json-patch
+ ${jsonpatch.version}
+
1.4.9
+ 1.12
diff --git a/spring-rest-http/src/main/java/com/baeldung/CustomerSpringBootRestApplication.java b/spring-rest-http/src/main/java/com/baeldung/CustomerSpringBootRestApplication.java
new file mode 100644
index 0000000000..2995d4d0dc
--- /dev/null
+++ b/spring-rest-http/src/main/java/com/baeldung/CustomerSpringBootRestApplication.java
@@ -0,0 +1,12 @@
+package com.baeldung;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class CustomerSpringBootRestApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CustomerSpringBootRestApplication.class, args);
+ }
+}
diff --git a/spring-rest-http/src/main/java/com/baeldung/model/Customer.java b/spring-rest-http/src/main/java/com/baeldung/model/Customer.java
new file mode 100644
index 0000000000..e65446c389
--- /dev/null
+++ b/spring-rest-http/src/main/java/com/baeldung/model/Customer.java
@@ -0,0 +1,79 @@
+package com.baeldung.model;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+public class Customer {
+ private String id;
+ private String telephone;
+ private List favorites;
+ private Map communicationPreferences;
+
+ public Customer() {
+ }
+
+ public Customer(String id, String telephone, List favorites, Map communicationPreferences) {
+ this(telephone, favorites, communicationPreferences);
+ this.id = id;
+ }
+
+ public Customer(String telephone, List favorites, Map communicationPreferences) {
+ this.telephone = telephone;
+ this.favorites = favorites;
+ this.communicationPreferences = communicationPreferences;
+ }
+
+ public static Customer fromCustomer(Customer customer) {
+ return new Customer(customer.getId(), customer.getTelephone(), customer.getFavorites(), customer.getCommunicationPreferences());
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getTelephone() {
+ return telephone;
+ }
+
+ public void setTelephone(String telephone) {
+ this.telephone = telephone;
+ }
+
+ public Map getCommunicationPreferences() {
+ return communicationPreferences;
+ }
+
+ public void setCommunicationPreferences(Map communicationPreferences) {
+ this.communicationPreferences = communicationPreferences;
+ }
+
+ public List getFavorites() {
+ return favorites;
+ }
+
+ public void setFavorites(List favorites) {
+ this.favorites = favorites;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Customer)) {
+ return false;
+ }
+ Customer customer = (Customer) o;
+ return Objects.equals(id, customer.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+}
diff --git a/spring-rest-http/src/main/java/com/baeldung/service/CustomerIdGenerator.java b/spring-rest-http/src/main/java/com/baeldung/service/CustomerIdGenerator.java
new file mode 100644
index 0000000000..f4afb79852
--- /dev/null
+++ b/spring-rest-http/src/main/java/com/baeldung/service/CustomerIdGenerator.java
@@ -0,0 +1,6 @@
+package com.baeldung.service;
+
+public interface CustomerIdGenerator {
+ int generateNextId();
+}
+
diff --git a/spring-rest-http/src/main/java/com/baeldung/service/CustomerService.java b/spring-rest-http/src/main/java/com/baeldung/service/CustomerService.java
new file mode 100644
index 0000000000..51a6bc7474
--- /dev/null
+++ b/spring-rest-http/src/main/java/com/baeldung/service/CustomerService.java
@@ -0,0 +1,14 @@
+package com.baeldung.service;
+
+import com.baeldung.model.Customer;
+
+import java.util.Optional;
+
+public interface CustomerService {
+
+ Customer createCustomer(Customer customer);
+
+ Optional findCustomer(String id);
+
+ void updateCustomer(Customer customer);
+}
diff --git a/spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerIdGeneratorImpl.java b/spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerIdGeneratorImpl.java
new file mode 100644
index 0000000000..471fe880b8
--- /dev/null
+++ b/spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerIdGeneratorImpl.java
@@ -0,0 +1,17 @@
+package com.baeldung.service.impl;
+
+import com.baeldung.service.CustomerIdGenerator;
+
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+@Component
+public class CustomerIdGeneratorImpl implements CustomerIdGenerator {
+ private static final AtomicInteger SEQUENCE = new AtomicInteger();
+
+ @Override
+ public int generateNextId() {
+ return SEQUENCE.incrementAndGet();
+ }
+}
diff --git a/spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerServiceImpl.java b/spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerServiceImpl.java
new file mode 100644
index 0000000000..c57e95deed
--- /dev/null
+++ b/spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerServiceImpl.java
@@ -0,0 +1,42 @@
+package com.baeldung.service.impl;
+
+import com.baeldung.model.Customer;
+import com.baeldung.service.CustomerIdGenerator;
+import com.baeldung.service.CustomerService;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class CustomerServiceImpl implements CustomerService {
+ private CustomerIdGenerator customerIdGenerator;
+ private List customers = new ArrayList<>();
+
+ @Autowired
+ public CustomerServiceImpl(CustomerIdGenerator customerIdGenerator) {
+ this.customerIdGenerator = customerIdGenerator;
+ }
+
+ @Override
+ public Customer createCustomer(Customer customer) {
+ customer.setId(Integer.toString(customerIdGenerator.generateNextId()));
+ customers.add(customer);
+ return customer;
+ }
+
+ @Override
+ public Optional findCustomer(String id) {
+ return customers.stream()
+ .filter(customer -> customer.getId().equals(id))
+ .findFirst();
+ }
+
+ @Override
+ public void updateCustomer(Customer customer) {
+ customers.set(customers.indexOf(customer), customer);
+ }
+}
diff --git a/spring-rest-http/src/main/java/com/baeldung/web/controller/CustomerRestController.java b/spring-rest-http/src/main/java/com/baeldung/web/controller/CustomerRestController.java
new file mode 100644
index 0000000000..9c248b6d2d
--- /dev/null
+++ b/spring-rest-http/src/main/java/com/baeldung/web/controller/CustomerRestController.java
@@ -0,0 +1,69 @@
+package com.baeldung.web.controller;
+
+import com.baeldung.model.Customer;
+import com.baeldung.service.CustomerService;
+import com.baeldung.web.exception.CustomerNotFoundException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.fge.jsonpatch.JsonPatch;
+import com.github.fge.jsonpatch.JsonPatchException;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PatchMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+import java.net.URI;
+
+import javax.validation.Valid;
+
+@RestController
+@RequestMapping(value = "/customers")
+public class CustomerRestController {
+ private CustomerService customerService;
+ private ObjectMapper objectMapper = new ObjectMapper();
+
+ @Autowired
+ public CustomerRestController(CustomerService customerService) {
+ this.customerService = customerService;
+ }
+
+ @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity createCustomer(@RequestBody Customer customer) {
+ Customer customerCreated = customerService.createCustomer(customer);
+ URI location = ServletUriComponentsBuilder.fromCurrentRequest()
+ .path("/{id}")
+ .buildAndExpand(customerCreated.getId())
+ .toUri();
+ return ResponseEntity.created(location).build();
+ }
+
+ @PatchMapping(path = "/{id}", consumes = "application/json-patch+json")
+ public ResponseEntity updateCustomer(@PathVariable String id,
+ @RequestBody JsonPatch patch) {
+ try {
+ Customer customer = customerService.findCustomer(id).orElseThrow(CustomerNotFoundException::new);
+ Customer customerPatched = applyPatchToCustomer(patch, customer);
+ customerService.updateCustomer(customerPatched);
+
+ return ResponseEntity.ok(customerPatched);
+ } catch (CustomerNotFoundException e) {
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
+ } catch (JsonPatchException | JsonProcessingException e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
+ }
+ }
+
+ private Customer applyPatchToCustomer(JsonPatch patch, Customer targetCustomer) throws JsonPatchException, JsonProcessingException {
+ JsonNode patched = patch.apply(objectMapper.convertValue(targetCustomer, JsonNode.class));
+ return objectMapper.treeToValue(patched, Customer.class);
+ }
+}
diff --git a/spring-rest-http/src/main/java/com/baeldung/web/exception/CustomerNotFoundException.java b/spring-rest-http/src/main/java/com/baeldung/web/exception/CustomerNotFoundException.java
new file mode 100644
index 0000000000..c843696402
--- /dev/null
+++ b/spring-rest-http/src/main/java/com/baeldung/web/exception/CustomerNotFoundException.java
@@ -0,0 +1,5 @@
+package com.baeldung.web.exception;
+
+public class CustomerNotFoundException extends RuntimeException {
+
+}
diff --git a/spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerIdGeneratorImplUnitTest.java b/spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerIdGeneratorImplUnitTest.java
new file mode 100644
index 0000000000..a855c1cda2
--- /dev/null
+++ b/spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerIdGeneratorImplUnitTest.java
@@ -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);
+ }
+}
diff --git a/spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerServiceImplUnitTest.java b/spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerServiceImplUnitTest.java
new file mode 100644
index 0000000000..27f0b35714
--- /dev/null
+++ b/spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerServiceImplUnitTest.java
@@ -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 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 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 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);
+ }
+}
\ No newline at end of file
diff --git a/spring-rest-http/src/test/java/com/baeldung/web/controller/CustomerRestControllerIntegrationTest.java b/spring-rest-http/src/test/java/com/baeldung/web/controller/CustomerRestControllerIntegrationTest.java
new file mode 100644
index 0000000000..f4d9ff1b92
--- /dev/null
+++ b/spring-rest-http/src/test/java/com/baeldung/web/controller/CustomerRestControllerIntegrationTest.java
@@ -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 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 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");
+ }
+}
diff --git a/spring-rest-http/src/test/java/com/baeldung/web/controller/CustomerRestControllerUnitTest.java b/spring-rest-http/src/test/java/com/baeldung/web/controller/CustomerRestControllerUnitTest.java
new file mode 100644
index 0000000000..d0fb255a5d
--- /dev/null
+++ b/spring-rest-http/src/test/java/com/baeldung/web/controller/CustomerRestControllerUnitTest.java
@@ -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 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 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)));
+ }
+}