#482 - Polishing.

This commit is contained in:
Oliver Gierke
2018-04-18 16:54:09 +02:00
parent d6e02857f1
commit 61972998ac
4 changed files with 262 additions and 268 deletions

View File

@@ -19,7 +19,6 @@ import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.collection.IsCollectionWithSize.*;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
@@ -91,68 +90,68 @@ public class CollectionJsonWebMvcIntegrationTest {
@Test
public void singleEmployee() throws Exception {
this.mockMvc.perform(get("/employees/0").accept(MediaTypes.COLLECTION_JSON_VALUE)) //
.andDo(print())
.andExpect(status().isOk()) //
this.mockMvc.perform(get("/employees/0") //
.accept(MediaTypes.COLLECTION_JSON_VALUE)) //
.andExpect(status().isOk()) //
.andExpect(jsonPath("$.collection.version", is("1.0")))
.andExpect(jsonPath("$.collection.href", is("http://localhost/employees/0")))
.andExpect(jsonPath("$.collection.version", is("1.0")))
.andExpect(jsonPath("$.collection.href", is("http://localhost/employees/0")))
.andExpect(jsonPath("$.collection.links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[0].data[1].value", is("Frodo Baggins")))
.andExpect(jsonPath("$.collection.items[0].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[0].data[0].value", is("ring bearer")))
.andExpect(jsonPath("$.collection.items.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[0].data[1].value", is("Frodo Baggins")))
.andExpect(jsonPath("$.collection.items[0].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[0].data[0].value", is("ring bearer")))
.andExpect(jsonPath("$.collection.items[0].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[0].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items[0].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[0].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.template.*", hasSize(1)))
.andExpect(jsonPath("$.collection.template.data[0].name", is("name")))
.andExpect(jsonPath("$.collection.template.data[0].value", is("")))
.andExpect(jsonPath("$.collection.template.data[1].name", is("role")))
.andExpect(jsonPath("$.collection.template.data[1].value", is("")));
.andExpect(jsonPath("$.collection.template.*", hasSize(1)))
.andExpect(jsonPath("$.collection.template.data[0].name", is("name")))
.andExpect(jsonPath("$.collection.template.data[0].value", is("")))
.andExpect(jsonPath("$.collection.template.data[1].name", is("role")))
.andExpect(jsonPath("$.collection.template.data[1].value", is("")));
}
@Test
public void collectionOfEmployees() throws Exception {
this.mockMvc.perform(get("/employees").accept(MediaTypes.COLLECTION_JSON_VALUE)) //
.andDo(print())
.andExpect(status().isOk()) //
this.mockMvc.perform(get("/employees") //
.accept(MediaTypes.COLLECTION_JSON_VALUE)) //
.andExpect(status().isOk()) //
.andExpect(jsonPath("$.collection.version", is("1.0")))
.andExpect(jsonPath("$.collection.href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.version", is("1.0")))
.andExpect(jsonPath("$.collection.href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items.*", hasSize(2)))
.andExpect(jsonPath("$.collection.items[0].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[0].data[1].value", is("Frodo Baggins")))
.andExpect(jsonPath("$.collection.items[0].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[0].data[0].value", is("ring bearer")))
.andExpect(jsonPath("$.collection.items.*", hasSize(2)))
.andExpect(jsonPath("$.collection.items[0].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[0].data[1].value", is("Frodo Baggins")))
.andExpect(jsonPath("$.collection.items[0].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[0].data[0].value", is("ring bearer")))
.andExpect(jsonPath("$.collection.items[0].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[0].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items[0].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[0].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items[1].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[1].data[1].value", is("Bilbo Baggins")))
.andExpect(jsonPath("$.collection.items[1].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[1].data[0].value", is("burglar")))
.andExpect(jsonPath("$.collection.items[1].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[1].data[1].value", is("Bilbo Baggins")))
.andExpect(jsonPath("$.collection.items[1].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[1].data[0].value", is("burglar")))
.andExpect(jsonPath("$.collection.items[1].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[1].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[1].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items[1].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[1].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[1].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.template.*", hasSize(1)))
.andExpect(jsonPath("$.collection.template.data[0].name", is("name")))
.andExpect(jsonPath("$.collection.template.data[0].value", is("")))
.andExpect(jsonPath("$.collection.template.data[1].name", is("role")))
.andExpect(jsonPath("$.collection.template.data[1].value", is("")));
.andExpect(jsonPath("$.collection.template.*", hasSize(1)))
.andExpect(jsonPath("$.collection.template.data[0].name", is("name")))
.andExpect(jsonPath("$.collection.template.data[0].value", is("")))
.andExpect(jsonPath("$.collection.template.data[1].name", is("role")))
.andExpect(jsonPath("$.collection.template.data[1].value", is("")));
}
@Test
@@ -160,39 +159,36 @@ public class CollectionJsonWebMvcIntegrationTest {
String specBasedJson = MappingUtils.read(new ClassPathResource("spec-part7-adjusted.json", getClass()));
this.mockMvc.perform(post("/employees")
.content(specBasedJson)
.contentType(MediaTypes.COLLECTION_JSON_VALUE))
.andDo(print())
.andExpect(status().isCreated())
.andExpect(header().stringValues(HttpHeaders.LOCATION, "http://localhost/employees/2"));
this.mockMvc.perform(post("/employees") //
.content(specBasedJson) //
.contentType(MediaTypes.COLLECTION_JSON_VALUE)) //
.andExpect(status().isCreated()) //
.andExpect(header().stringValues(HttpHeaders.LOCATION, "http://localhost/employees/2"));
this.mockMvc.perform(get("/employees/2").accept(MediaTypes.COLLECTION_JSON))
.andDo(print())
.andExpect(status().isOk()) //
this.mockMvc.perform(get("/employees/2").accept(MediaTypes.COLLECTION_JSON)).andExpect(status().isOk()) //
.andExpect(jsonPath("$.collection.version", is("1.0")))
.andExpect(jsonPath("$.collection.href", is("http://localhost/employees/2")))
.andExpect(jsonPath("$.collection.version", is("1.0")))
.andExpect(jsonPath("$.collection.href", is("http://localhost/employees/2")))
.andExpect(jsonPath("$.collection.links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[0].data[1].value", is("W. Chandry")))
.andExpect(jsonPath("$.collection.items[0].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[0].data[0].value", is("developer")))
.andExpect(jsonPath("$.collection.items.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[0].data[1].value", is("W. Chandry")))
.andExpect(jsonPath("$.collection.items[0].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[0].data[0].value", is("developer")))
.andExpect(jsonPath("$.collection.items[0].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[0].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items[0].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[0].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.template.*", hasSize(1)))
.andExpect(jsonPath("$.collection.template.data[0].name", is("name")))
.andExpect(jsonPath("$.collection.template.data[0].value", is("")))
.andExpect(jsonPath("$.collection.template.data[1].name", is("role")))
.andExpect(jsonPath("$.collection.template.data[1].value", is("")));
.andExpect(jsonPath("$.collection.template.*", hasSize(1)))
.andExpect(jsonPath("$.collection.template.data[0].name", is("name")))
.andExpect(jsonPath("$.collection.template.data[0].value", is("")))
.andExpect(jsonPath("$.collection.template.data[1].name", is("role")))
.andExpect(jsonPath("$.collection.template.data[1].value", is("")));
}
@RestController
@@ -219,8 +215,8 @@ public class CollectionJsonWebMvcIntegrationTest {
}
@GetMapping("/employees/search")
public Resources<Resource<Employee>> search(@RequestParam(value="name", required=false) String name,
@RequestParam(value="role", required=false) String role) {
public Resources<Resource<Employee>> search(@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "role", required = false) String role) {
// Create a list of Resource<Employee>'s to return
List<Resource<Employee>> employees = new ArrayList<>();
@@ -229,13 +225,11 @@ public class CollectionJsonWebMvcIntegrationTest {
for (int i = 0; i < EMPLOYEES.size(); i++) {
Resource<Employee> employeeResource = findOne(i);
boolean nameMatches = Optional.ofNullable(name)
.map(s -> employeeResource.getContent().getName().contains(s))
.orElse(true);
boolean nameMatches = Optional.ofNullable(name).map(s -> employeeResource.getContent().getName().contains(s))
.orElse(true);
boolean roleMatches = Optional.ofNullable(role)
.map( s -> employeeResource.getContent().getRole().contains(s))
.orElse(true);
boolean roleMatches = Optional.ofNullable(role).map(s -> employeeResource.getContent().getRole().contains(s))
.orElse(true);
if (nameMatches && roleMatches) {
employees.add(employeeResource);
@@ -244,8 +238,8 @@ public class CollectionJsonWebMvcIntegrationTest {
// Generate an "Affordance" based on this method (the "self" link)
Link selfLink = linkTo(methodOn(EmployeeController.class).all()).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).newEmployee(null)))
.andAffordance(afford(methodOn(EmployeeController.class).search(null, null)));
.andAffordance(afford(methodOn(EmployeeController.class).newEmployee(null)))
.andAffordance(afford(methodOn(EmployeeController.class).search(null, null)));
// Return the collection of employee resources along with the composite affordance
return new Resources<>(employees, selfLink);
@@ -262,9 +256,9 @@ public class CollectionJsonWebMvcIntegrationTest {
// Return the affordance + a link back to the entire collection resource.
return new Resource<>(EMPLOYEES.get(id),
findOneLink.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, id))) //
.andAffordance(afford(methodOn(EmployeeController.class).partiallyUpdateEmployee(null, id))),
employeesLink);
findOneLink.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, id))) //
.andAffordance(afford(methodOn(EmployeeController.class).partiallyUpdateEmployee(null, id))),
employeesLink);
}
@PostMapping("/employees")
@@ -275,8 +269,10 @@ public class CollectionJsonWebMvcIntegrationTest {
EMPLOYEES.put(newEmployeeId, employee.getContent());
try {
return ResponseEntity.created(new URI(findOne(newEmployeeId).getLink(Link.REL_SELF).map(link -> link.expand().getHref()).orElse("")))
.build();
return ResponseEntity
.created(
new URI(findOne(newEmployeeId).getLink(Link.REL_SELF).map(link -> link.expand().getHref()).orElse("")))
.build();
} catch (URISyntaxException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
@@ -288,15 +284,17 @@ public class CollectionJsonWebMvcIntegrationTest {
EMPLOYEES.put(id, employee.getContent());
try {
return ResponseEntity.noContent().location(new URI(findOne(id).getLink(Link.REL_SELF).map(link -> link.expand().getHref()).orElse("")))
.build();
return ResponseEntity.noContent()
.location(new URI(findOne(id).getLink(Link.REL_SELF).map(link -> link.expand().getHref()).orElse("")))
.build();
} catch (URISyntaxException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
@PatchMapping("/employees/{id}")
public ResponseEntity<?> partiallyUpdateEmployee(@RequestBody Resource<Employee> employee, @PathVariable Integer id) {
public ResponseEntity<?> partiallyUpdateEmployee(@RequestBody Resource<Employee> employee,
@PathVariable Integer id) {
Employee oldEmployee = EMPLOYEES.get(id);
Employee newEmployee = oldEmployee;
@@ -312,8 +310,9 @@ public class CollectionJsonWebMvcIntegrationTest {
EMPLOYEES.put(id, newEmployee);
try {
return ResponseEntity.noContent().location(new URI(findOne(id).getLink(Link.REL_SELF).map(link -> link.expand().getHref()).orElse("")))
.build();
return ResponseEntity.noContent()
.location(new URI(findOne(id).getLink(Link.REL_SELF).map(link -> link.expand().getHref()).orElse("")))
.build();
} catch (URISyntaxException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
@@ -322,7 +321,7 @@ public class CollectionJsonWebMvcIntegrationTest {
@Configuration
@EnableWebMvc
@EnableHypermediaSupport(type = { HypermediaType.COLLECTION_JSON})
@EnableHypermediaSupport(type = { HypermediaType.COLLECTION_JSON })
static class TestConfig {
@Bean

View File

@@ -19,7 +19,6 @@ import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.collection.IsCollectionWithSize.*;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
@@ -131,12 +130,11 @@ public class HalFormsWebMvcIntegrationTest {
String specBasedJson = MappingUtils.read(new ClassPathResource("new-employee.json", getClass()));
this.mockMvc.perform(post("/employees")
.content(specBasedJson)
.contentType(MediaTypes.HAL_FORMS_JSON_VALUE))
.andDo(print())
.andExpect(status().isCreated())
.andExpect(header().stringValues(HttpHeaders.LOCATION, "http://localhost/employees/2"));
this.mockMvc.perform(post("/employees") //
.content(specBasedJson) //
.contentType(MediaTypes.HAL_FORMS_JSON_VALUE)) //
.andExpect(status().isCreated())
.andExpect(header().stringValues(HttpHeaders.LOCATION, "http://localhost/employees/2"));
}
@RestController
@@ -161,7 +159,7 @@ public class HalFormsWebMvcIntegrationTest {
}
// Generate an "Affordance" based on this method (the "self" link)
Link selfLink = linkTo(methodOn(EmployeeController.class).all()).withSelfRel()
Link selfLink = linkTo(methodOn(EmployeeController.class).all()).withSelfRel() //
.andAffordance(afford(methodOn(EmployeeController.class).newEmployee(null)));
// Return the collection of employee resources along with the composite affordance
@@ -178,10 +176,10 @@ public class HalFormsWebMvcIntegrationTest {
Link employeesLink = linkTo(methodOn(EmployeeController.class).all()).withRel("employees");
// Return the affordance + a link back to the entire collection resource.
return new Resource<>(EMPLOYEES.get(id),
findOneLink.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, id))) //
.andAffordance(afford(methodOn(EmployeeController.class).partiallyUpdateEmployee(null, id))),
employeesLink);
return new Resource<>(EMPLOYEES.get(id), //
findOneLink.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, id))) //
.andAffordance(afford(methodOn(EmployeeController.class).partiallyUpdateEmployee(null, id))),
employeesLink);
}
@PostMapping("/employees")
@@ -192,8 +190,7 @@ public class HalFormsWebMvcIntegrationTest {
EMPLOYEES.put(newEmployeeId, employee);
try {
return ResponseEntity.created(new URI(findOne(newEmployeeId).getLink(Link.REL_SELF).map(link -> link.expand().getHref()).orElse("")))
.build();
return ResponseEntity.created(toUri(newEmployeeId)).build();
} catch (URISyntaxException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
@@ -205,8 +202,7 @@ public class HalFormsWebMvcIntegrationTest {
EMPLOYEES.put(id, employee);
try {
return ResponseEntity.noContent().location(new URI(findOne(id).getLink(Link.REL_SELF).map(link -> link.expand().getHref()).orElse("")))
.build();
return ResponseEntity.noContent().location(toUri(id)).build();
} catch (URISyntaxException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
@@ -229,12 +225,20 @@ public class HalFormsWebMvcIntegrationTest {
EMPLOYEES.put(id, newEmployee);
try {
return ResponseEntity.noContent().location(new URI(findOne(id).getLink(Link.REL_SELF).map(link -> link.expand().getHref()).orElse("")))
.build();
return ResponseEntity.noContent().location(toUri(id)).build();
} catch (URISyntaxException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
private URI toUri(Integer id) throws URISyntaxException {
String uri = findOne(id).getLink(Link.REL_SELF) //
.map(link -> link.expand().getHref()) //
.orElse("");
return new URI(uri);
}
}
@Configuration

View File

@@ -19,7 +19,6 @@ import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.collection.IsCollectionWithSize.*;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
@@ -78,7 +77,7 @@ public class MultiMediatypeWebMvcIntegrationTest {
MockMvc mockMvc;
private static Map<Integer, Employee> EMPLOYEES;
@Before
public void setUp() {
@@ -94,133 +93,126 @@ public class MultiMediatypeWebMvcIntegrationTest {
public void singleEmployeeCollectionJson() throws Exception {
this.mockMvc.perform(get("/employees/0").accept(MediaTypes.COLLECTION_JSON_VALUE)) //
.andDo(print())
.andExpect(status().isOk()) //
.andExpect(status().isOk()) //
.andExpect(jsonPath("$.collection.version", is("1.0")))
.andExpect(jsonPath("$.collection.href", is("http://localhost/employees/0")))
.andExpect(jsonPath("$.collection.version", is("1.0")))
.andExpect(jsonPath("$.collection.href", is("http://localhost/employees/0")))
.andExpect(jsonPath("$.collection.links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[0].data[1].value", is("Frodo Baggins")))
.andExpect(jsonPath("$.collection.items[0].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[0].data[0].value", is("ring bearer")))
.andExpect(jsonPath("$.collection.items.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[0].data[1].value", is("Frodo Baggins")))
.andExpect(jsonPath("$.collection.items[0].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[0].data[0].value", is("ring bearer")))
.andExpect(jsonPath("$.collection.items[0].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[0].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items[0].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[0].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.template.*", hasSize(1)))
.andExpect(jsonPath("$.collection.template.data[0].name", is("name")))
.andExpect(jsonPath("$.collection.template.data[0].value", is("")))
.andExpect(jsonPath("$.collection.template.data[1].name", is("role")))
.andExpect(jsonPath("$.collection.template.data[1].value", is("")));
.andExpect(jsonPath("$.collection.template.*", hasSize(1)))
.andExpect(jsonPath("$.collection.template.data[0].name", is("name")))
.andExpect(jsonPath("$.collection.template.data[0].value", is("")))
.andExpect(jsonPath("$.collection.template.data[1].name", is("role")))
.andExpect(jsonPath("$.collection.template.data[1].value", is("")));
}
@Test
public void collectionOfEmployeesCollectionJson() throws Exception {
this.mockMvc.perform(get("/employees").accept(MediaTypes.COLLECTION_JSON_VALUE)) //
.andDo(print())
.andExpect(status().isOk()) //
.andExpect(status().isOk()) //
.andExpect(jsonPath("$.collection.version", is("1.0")))
.andExpect(jsonPath("$.collection.href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.version", is("1.0")))
.andExpect(jsonPath("$.collection.href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items.*", hasSize(2)))
.andExpect(jsonPath("$.collection.items[0].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[0].data[1].value", is("Frodo Baggins")))
.andExpect(jsonPath("$.collection.items[0].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[0].data[0].value", is("ring bearer")))
.andExpect(jsonPath("$.collection.items.*", hasSize(2)))
.andExpect(jsonPath("$.collection.items[0].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[0].data[1].value", is("Frodo Baggins")))
.andExpect(jsonPath("$.collection.items[0].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[0].data[0].value", is("ring bearer")))
.andExpect(jsonPath("$.collection.items[0].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[0].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items[0].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[0].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items[1].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[1].data[1].value", is("Bilbo Baggins")))
.andExpect(jsonPath("$.collection.items[1].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[1].data[0].value", is("burglar")))
.andExpect(jsonPath("$.collection.items[1].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[1].data[1].value", is("Bilbo Baggins")))
.andExpect(jsonPath("$.collection.items[1].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[1].data[0].value", is("burglar")))
.andExpect(jsonPath("$.collection.items[1].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[1].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[1].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items[1].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[1].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[1].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.template.*", hasSize(1)))
.andExpect(jsonPath("$.collection.template.data[0].name", is("name")))
.andExpect(jsonPath("$.collection.template.data[0].value", is("")))
.andExpect(jsonPath("$.collection.template.data[1].name", is("role")))
.andExpect(jsonPath("$.collection.template.data[1].value", is("")));
.andExpect(jsonPath("$.collection.template.*", hasSize(1)))
.andExpect(jsonPath("$.collection.template.data[0].name", is("name")))
.andExpect(jsonPath("$.collection.template.data[0].value", is("")))
.andExpect(jsonPath("$.collection.template.data[1].name", is("role")))
.andExpect(jsonPath("$.collection.template.data[1].value", is("")));
}
@Test
public void createNewEmployeeCollectionJson() throws Exception {
String specBasedJson = MappingUtils.read(new ClassPathResource("../collectionjson/spec-part7-adjusted.json", getClass()));
String specBasedJson = MappingUtils
.read(new ClassPathResource("../collectionjson/spec-part7-adjusted.json", getClass()));
this.mockMvc.perform(post("/employees")
.content(specBasedJson)
.contentType(MediaTypes.COLLECTION_JSON_VALUE))
.andDo(print())
.andExpect(status().isCreated())
.andExpect(header().stringValues(HttpHeaders.LOCATION, "http://localhost/employees/2"));
this.mockMvc.perform(post("/employees").content(specBasedJson).contentType(MediaTypes.COLLECTION_JSON_VALUE))
.andExpect(status().isCreated())
.andExpect(header().stringValues(HttpHeaders.LOCATION, "http://localhost/employees/2"));
this.mockMvc.perform(get("/employees/2").accept(MediaTypes.COLLECTION_JSON))
.andDo(print())
.andExpect(status().isOk()) //
this.mockMvc.perform(get("/employees/2").accept(MediaTypes.COLLECTION_JSON)).andExpect(status().isOk()) //
.andExpect(jsonPath("$.collection.version", is("1.0")))
.andExpect(jsonPath("$.collection.href", is("http://localhost/employees/2")))
.andExpect(jsonPath("$.collection.version", is("1.0")))
.andExpect(jsonPath("$.collection.href", is("http://localhost/employees/2")))
.andExpect(jsonPath("$.collection.links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[0].data[1].value", is("W. Chandry")))
.andExpect(jsonPath("$.collection.items[0].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[0].data[0].value", is("developer")))
.andExpect(jsonPath("$.collection.items.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].data[1].name", is("name")))
.andExpect(jsonPath("$.collection.items[0].data[1].value", is("W. Chandry")))
.andExpect(jsonPath("$.collection.items[0].data[0].name", is("role")))
.andExpect(jsonPath("$.collection.items[0].data[0].value", is("developer")))
.andExpect(jsonPath("$.collection.items[0].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[0].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.items[0].links.*", hasSize(1)))
.andExpect(jsonPath("$.collection.items[0].links[0].rel", is("employees")))
.andExpect(jsonPath("$.collection.items[0].links[0].href", is("http://localhost/employees")))
.andExpect(jsonPath("$.collection.template.*", hasSize(1)))
.andExpect(jsonPath("$.collection.template.data[0].name", is("name")))
.andExpect(jsonPath("$.collection.template.data[0].value", is("")))
.andExpect(jsonPath("$.collection.template.data[1].name", is("role")))
.andExpect(jsonPath("$.collection.template.data[1].value", is("")));
.andExpect(jsonPath("$.collection.template.*", hasSize(1)))
.andExpect(jsonPath("$.collection.template.data[0].name", is("name")))
.andExpect(jsonPath("$.collection.template.data[0].value", is("")))
.andExpect(jsonPath("$.collection.template.data[1].name", is("role")))
.andExpect(jsonPath("$.collection.template.data[1].value", is("")));
}
@Test
public void singleEmployeeHalForms() throws Exception {
this.mockMvc.perform(get("/employees/0").accept(MediaTypes.HAL_FORMS_JSON)) //
.andDo(print())
.andExpect(status().isOk()) //
.andExpect(jsonPath("$.name", is("Frodo Baggins"))).andExpect(jsonPath("$.role", is("ring bearer")))
.andExpect(status().isOk()) //
.andExpect(jsonPath("$.name", is("Frodo Baggins"))).andExpect(jsonPath("$.role", is("ring bearer")))
.andExpect(jsonPath("$._links.*", hasSize(2)))
.andExpect(jsonPath("$._links['self'].href", is("http://localhost/employees/0")))
.andExpect(jsonPath("$._links['employees'].href", is("http://localhost/employees")))
.andExpect(jsonPath("$._links.*", hasSize(2)))
.andExpect(jsonPath("$._links['self'].href", is("http://localhost/employees/0")))
.andExpect(jsonPath("$._links['employees'].href", is("http://localhost/employees")))
.andExpect(jsonPath("$._templates.*", hasSize(2)))
.andExpect(jsonPath("$._templates['default'].method", is("put")))
.andExpect(jsonPath("$._templates['default'].properties[0].name", is("name")))
.andExpect(jsonPath("$._templates['default'].properties[0].required", is(true)))
.andExpect(jsonPath("$._templates['default'].properties[1].name", is("role")))
.andExpect(jsonPath("$._templates['default'].properties[1].required", is(true)))
.andExpect(jsonPath("$._templates.*", hasSize(2)))
.andExpect(jsonPath("$._templates['default'].method", is("put")))
.andExpect(jsonPath("$._templates['default'].properties[0].name", is("name")))
.andExpect(jsonPath("$._templates['default'].properties[0].required", is(true)))
.andExpect(jsonPath("$._templates['default'].properties[1].name", is("role")))
.andExpect(jsonPath("$._templates['default'].properties[1].required", is(true)))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].method", is("patch")))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[0].name", is("name")))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[0].required", is(false)))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[1].name", is("role")))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[1].required", is(false)));
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].method", is("patch")))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[0].name", is("name")))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[0].required", is(false)))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[1].name", is("role")))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[1].required", is(false)));
;
}
@@ -228,24 +220,23 @@ public class MultiMediatypeWebMvcIntegrationTest {
public void collectionOfEmployeesHalForms() throws Exception {
this.mockMvc.perform(get("/employees").accept(MediaTypes.HAL_FORMS_JSON)) //
.andDo(print())
.andExpect(status().isOk()) //
.andExpect(jsonPath("$._embedded.employees[0].name", is("Frodo Baggins")))
.andExpect(jsonPath("$._embedded.employees[0].role", is("ring bearer")))
.andExpect(jsonPath("$._embedded.employees[0]._links['self'].href", is("http://localhost/employees/0")))
.andExpect(jsonPath("$._embedded.employees[1].name", is("Bilbo Baggins")))
.andExpect(jsonPath("$._embedded.employees[1].role", is("burglar")))
.andExpect(jsonPath("$._embedded.employees[1]._links['self'].href", is("http://localhost/employees/1")))
.andExpect(status().isOk()) //
.andExpect(jsonPath("$._embedded.employees[0].name", is("Frodo Baggins")))
.andExpect(jsonPath("$._embedded.employees[0].role", is("ring bearer")))
.andExpect(jsonPath("$._embedded.employees[0]._links['self'].href", is("http://localhost/employees/0")))
.andExpect(jsonPath("$._embedded.employees[1].name", is("Bilbo Baggins")))
.andExpect(jsonPath("$._embedded.employees[1].role", is("burglar")))
.andExpect(jsonPath("$._embedded.employees[1]._links['self'].href", is("http://localhost/employees/1")))
.andExpect(jsonPath("$._links.*", hasSize(1)))
.andExpect(jsonPath("$._links['self'].href", is("http://localhost/employees")))
.andExpect(jsonPath("$._links.*", hasSize(1)))
.andExpect(jsonPath("$._links['self'].href", is("http://localhost/employees")))
.andExpect(jsonPath("$._templates.*", hasSize(1)))
.andExpect(jsonPath("$._templates['default'].method", is("post")))
.andExpect(jsonPath("$._templates['default'].properties[0].name", is("name")))
.andExpect(jsonPath("$._templates['default'].properties[0].required", is(true)))
.andExpect(jsonPath("$._templates['default'].properties[1].name", is("role")))
.andExpect(jsonPath("$._templates['default'].properties[1].required", is(true)));
.andExpect(jsonPath("$._templates.*", hasSize(1)))
.andExpect(jsonPath("$._templates['default'].method", is("post")))
.andExpect(jsonPath("$._templates['default'].properties[0].name", is("name")))
.andExpect(jsonPath("$._templates['default'].properties[0].required", is(true)))
.andExpect(jsonPath("$._templates['default'].properties[1].name", is("role")))
.andExpect(jsonPath("$._templates['default'].properties[1].required", is(true)));
}
@Test
@@ -253,36 +244,32 @@ public class MultiMediatypeWebMvcIntegrationTest {
String specBasedJson = MappingUtils.read(new ClassPathResource("../hal/forms/new-employee.json", getClass()));
this.mockMvc.perform(post("/employees")
.content(specBasedJson)
.contentType(MediaTypes.HAL_FORMS_JSON_VALUE))
.andDo(print())
.andExpect(status().isCreated())
.andExpect(header().stringValues(HttpHeaders.LOCATION, "http://localhost/employees/2"));
this.mockMvc.perform(post("/employees").content(specBasedJson).contentType(MediaTypes.HAL_FORMS_JSON_VALUE))
.andExpect(status().isCreated())
.andExpect(header().stringValues(HttpHeaders.LOCATION, "http://localhost/employees/2"));
this.mockMvc.perform(get("/employees/2").accept(MediaTypes.HAL_FORMS_JSON)) //
.andDo(print())
.andExpect(status().isOk()) //
.andExpect(jsonPath("$.name", is("Samwise Gamgee"))).andExpect(jsonPath("$.role", is("gardener")))
.andExpect(status().isOk()) //
.andExpect(jsonPath("$.name", is("Samwise Gamgee"))).andExpect(jsonPath("$.role", is("gardener")))
.andExpect(jsonPath("$._links.*", hasSize(2)))
.andExpect(jsonPath("$._links['self'].href", is("http://localhost/employees/2")))
.andExpect(jsonPath("$._links['employees'].href", is("http://localhost/employees")))
.andExpect(jsonPath("$._links.*", hasSize(2)))
.andExpect(jsonPath("$._links['self'].href", is("http://localhost/employees/2")))
.andExpect(jsonPath("$._links['employees'].href", is("http://localhost/employees")))
.andExpect(jsonPath("$._templates.*", hasSize(2)))
.andExpect(jsonPath("$._templates['default'].method", is("put")))
.andExpect(jsonPath("$._templates['default'].properties[0].name", is("name")))
.andExpect(jsonPath("$._templates['default'].properties[0].required", is(true)))
.andExpect(jsonPath("$._templates['default'].properties[1].name", is("role")))
.andExpect(jsonPath("$._templates['default'].properties[1].required", is(true)))
.andExpect(jsonPath("$._templates.*", hasSize(2)))
.andExpect(jsonPath("$._templates['default'].method", is("put")))
.andExpect(jsonPath("$._templates['default'].properties[0].name", is("name")))
.andExpect(jsonPath("$._templates['default'].properties[0].required", is(true)))
.andExpect(jsonPath("$._templates['default'].properties[1].name", is("role")))
.andExpect(jsonPath("$._templates['default'].properties[1].required", is(true)))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].method", is("patch")))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[0].name", is("name")))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[0].required", is(false)))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[1].name", is("role")))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[1].required", is(false)));
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].method", is("patch")))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[0].name", is("name")))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[0].required", is(false)))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[1].name", is("role")))
.andExpect(jsonPath("$._templates['partiallyUpdateEmployee'].properties[1].required", is(false)));
}
@RestController
static class EmployeeController {
@@ -299,16 +286,16 @@ public class MultiMediatypeWebMvcIntegrationTest {
// Generate an "Affordance" based on this method (the "self" link)
Link selfLink = linkTo(methodOn(EmployeeController.class).all()).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).newEmployee(null)))
.andAffordance(afford(methodOn(EmployeeController.class).search(null, null)));
.andAffordance(afford(methodOn(EmployeeController.class).newEmployee(null)))
.andAffordance(afford(methodOn(EmployeeController.class).search(null, null)));
// Return the collection of employee resources along with the composite affordance
return new Resources<>(employees, selfLink);
}
@GetMapping("/employees/search")
public Resources<Resource<Employee>> search(@RequestParam(value="name", required=false) String name,
@RequestParam(value="role", required=false) String role) {
public Resources<Resource<Employee>> search(@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "role", required = false) String role) {
// Create a list of Resource<Employee>'s to return
List<Resource<Employee>> employees = new ArrayList<>();
@@ -317,13 +304,11 @@ public class MultiMediatypeWebMvcIntegrationTest {
for (int i = 0; i < EMPLOYEES.size(); i++) {
Resource<Employee> employeeResource = findOne(i);
boolean nameMatches = Optional.ofNullable(name)
.map(s -> employeeResource.getContent().getName().contains(s))
.orElse(true);
boolean nameMatches = Optional.ofNullable(name).map(s -> employeeResource.getContent().getName().contains(s))
.orElse(true);
boolean roleMatches = Optional.ofNullable(role)
.map( s -> employeeResource.getContent().getRole().contains(s))
.orElse(true);
boolean roleMatches = Optional.ofNullable(role).map(s -> employeeResource.getContent().getRole().contains(s))
.orElse(true);
if (nameMatches && roleMatches) {
employees.add(employeeResource);
@@ -332,8 +317,8 @@ public class MultiMediatypeWebMvcIntegrationTest {
// Generate an "Affordance" based on this method (the "self" link)
Link selfLink = linkTo(methodOn(EmployeeController.class).all()).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).newEmployee(null)))
.andAffordance(afford(methodOn(EmployeeController.class).search(null, null)));
.andAffordance(afford(methodOn(EmployeeController.class).newEmployee(null)))
.andAffordance(afford(methodOn(EmployeeController.class).search(null, null)));
// Return the collection of employee resources along with the composite affordance
return new Resources<>(employees, selfLink);
@@ -350,9 +335,9 @@ public class MultiMediatypeWebMvcIntegrationTest {
// Return the affordance + a link back to the entire collection resource.
return new Resource<>(EMPLOYEES.get(id),
findOneLink.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, id))) //
.andAffordance(afford(methodOn(EmployeeController.class).partiallyUpdateEmployee(null, id))),
employeesLink);
findOneLink.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, id))) //
.andAffordance(afford(methodOn(EmployeeController.class).partiallyUpdateEmployee(null, id))),
employeesLink);
}
@PostMapping("/employees")
@@ -363,8 +348,7 @@ public class MultiMediatypeWebMvcIntegrationTest {
EMPLOYEES.put(newEmployeeId, employee.getContent());
try {
return ResponseEntity.created(new URI(findOne(newEmployeeId).getLink(Link.REL_SELF).map(link -> link.expand().getHref()).orElse("")))
.build();
return ResponseEntity.created(toUri(newEmployeeId)).build();
} catch (URISyntaxException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
@@ -376,15 +360,15 @@ public class MultiMediatypeWebMvcIntegrationTest {
EMPLOYEES.put(id, employee.getContent());
try {
return ResponseEntity.noContent().location(new URI(findOne(id).getLink(Link.REL_SELF).map(link -> link.expand().getHref()).orElse("")))
.build();
return ResponseEntity.noContent().location(toUri(id)).build();
} catch (URISyntaxException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
@PatchMapping("/employees/{id}")
public ResponseEntity<?> partiallyUpdateEmployee(@RequestBody Resource<Employee> employee, @PathVariable Integer id) {
public ResponseEntity<?> partiallyUpdateEmployee(@RequestBody Resource<Employee> employee,
@PathVariable Integer id) {
Employee oldEmployee = EMPLOYEES.get(id);
Employee newEmployee = oldEmployee;
@@ -400,12 +384,21 @@ public class MultiMediatypeWebMvcIntegrationTest {
EMPLOYEES.put(id, newEmployee);
try {
return ResponseEntity.noContent().location(new URI(findOne(id).getLink(Link.REL_SELF).map(link -> link.expand().getHref()).orElse("")))
.build();
return ResponseEntity.noContent().location(toUri(id)).build();
} catch (URISyntaxException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
private URI toUri(Integer id) throws URISyntaxException {
String uri = findOne(id) //
.getLink(Link.REL_SELF) //
.map(link -> link.expand().getHref()) //
.orElse("");
return new URI(uri);
}
}
@Configuration

View File

@@ -20,7 +20,6 @@ import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import static org.springframework.util.ReflectionUtils.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -48,7 +47,6 @@ import org.springframework.hateoas.mvc.ResourceProcessorInvoker.ResourcesProcess
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ReflectionUtils.MethodCallback;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
/**