diff --git a/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java b/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java index 4cb9ffc0c..3b47a954c 100644 --- a/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java +++ b/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java @@ -15,12 +15,11 @@ */ package org.springframework.samples.petclinic.model; -import java.io.Serializable; - import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.MappedSuperclass; +import java.io.Serializable; /** * Simple JavaBean domain object with an id property. Used as a base class for objects diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java index 61083bc8d..7f2ef905e 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java @@ -24,6 +24,7 @@ import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.validation.constraints.Digits; @@ -59,7 +60,7 @@ public class Owner extends Person { @Digits(fraction = 0, integer = 10) private String telephone; - @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner") + @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner", fetch = FetchType.EAGER) private Set pets; public String getAddress() { diff --git a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java index 79aa4cd9b..781184ae2 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java @@ -15,6 +15,14 @@ */ package org.springframework.samples.petclinic.owner; +import java.util.List; +import java.util.Map; + +import javax.validation.Valid; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.samples.petclinic.visit.VisitRepository; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -24,12 +32,9 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; -import javax.validation.Valid; -import java.util.Collection; -import java.util.Map; - /** * @author Juergen Hoeller * @author Ken Krebs @@ -43,7 +48,7 @@ class OwnerController { private final OwnerRepository owners; - private VisitRepository visits; + private final VisitRepository visits; public OwnerController(OwnerRepository clinicService, VisitRepository visits) { this.owners = clinicService; @@ -80,7 +85,8 @@ class OwnerController { } @GetMapping("/owners") - public String processFindForm(Owner owner, BindingResult result, Map model) { + public String processFindForm(@RequestParam(defaultValue = "1") int page, Owner owner, BindingResult result, + Model model) { // allow parameterless GET request for /owners to return all records if (owner.getLastName() == null) { @@ -88,24 +94,43 @@ class OwnerController { } // find owners by last name - Collection results = this.owners.findByLastName(owner.getLastName()); - if (results.isEmpty()) { + String lastName = owner.getLastName(); + Page ownersResults = findPaginatedForOwnersLastName(page, lastName); + if (ownersResults.isEmpty()) { // no owners found result.rejectValue("lastName", "notFound", "not found"); return "owners/findOwners"; } - else if (results.size() == 1) { + else if (ownersResults.getTotalElements() == 1) { // 1 owner found - owner = results.iterator().next(); + owner = ownersResults.iterator().next(); return "redirect:/owners/" + owner.getId(); } else { // multiple owners found - model.put("selections", results); - return "owners/ownersList"; + lastName = owner.getLastName(); + return addPaginationModel(page, model, lastName, ownersResults); } } + private String addPaginationModel(int page, Model model, String lastName, Page paginated) { + model.addAttribute("listOwners", paginated); + List listOwners = paginated.getContent(); + model.addAttribute("currentPage", page); + model.addAttribute("totalPages", paginated.getTotalPages()); + model.addAttribute("totalItems", paginated.getTotalElements()); + model.addAttribute("listOwners", listOwners); + return "owners/ownersList"; + } + + private Page findPaginatedForOwnersLastName(int page, String lastname) { + + int pageSize = 5; + Pageable pageable = PageRequest.of(page - 1, pageSize); + return owners.findByLastName(lastname, pageable); + + } + @GetMapping("/owners/{ownerId}/edit") public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) { Owner owner = this.owners.findById(ownerId); diff --git a/src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java b/src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java index 0613e928a..091510122 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java @@ -15,8 +15,8 @@ */ package org.springframework.samples.petclinic.owner; -import java.util.Collection; - +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; import org.springframework.data.repository.query.Param; @@ -42,9 +42,10 @@ public interface OwnerRepository extends Repository { * @return a Collection of matching {@link Owner}s (or an empty Collection if none * found) */ - @Query("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.lastName LIKE :lastName%") + + @Query("SELECT DISTINCT owner FROM Owner owner left join owner.pets WHERE owner.lastName LIKE :lastName% ") @Transactional(readOnly = true) - Collection findByLastName(@Param("lastName") String lastName); + Page findByLastName(@Param("lastName") String lastName, Pageable pageable); /** * Retrieve an {@link Owner} from the data store by id. @@ -61,4 +62,11 @@ public interface OwnerRepository extends Repository { */ void save(Owner owner); + /** + * Returnes all the owners from data store + **/ + @Query("SELECT owner FROM Owner owner") + @Transactional(readOnly = true) + Page findAll(Pageable pageable); + } diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetRepository.java b/src/main/java/org/springframework/samples/petclinic/owner/PetRepository.java index 9d25b095b..069f9f37c 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/PetRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/PetRepository.java @@ -15,12 +15,12 @@ */ package org.springframework.samples.petclinic.owner; -import java.util.List; - import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + /** * Repository class for Pet domain objects All method names are compliant * with Spring Data naming conventions so this interface can easily be extended for Spring diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetType.java b/src/main/java/org/springframework/samples/petclinic/owner/PetType.java index 6f0aa58d3..3cb9fc1d0 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/PetType.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/PetType.java @@ -15,11 +15,11 @@ */ package org.springframework.samples.petclinic.owner; +import org.springframework.samples.petclinic.model.NamedEntity; + import javax.persistence.Entity; import javax.persistence.Table; -import org.springframework.samples.petclinic.model.NamedEntity; - /** * @author Juergen Hoeller Can be Cat, Dog, Hamster... */ diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java b/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java index 4940bcb38..c97107f2e 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java @@ -15,14 +15,14 @@ */ package org.springframework.samples.petclinic.owner; -import java.text.ParseException; -import java.util.Collection; -import java.util.Locale; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.format.Formatter; import org.springframework.stereotype.Component; +import java.text.ParseException; +import java.util.Collection; +import java.util.Locale; + /** * Instructs Spring MVC on how to parse and print elements of type 'PetType'. Starting * from Spring 3.0, Formatters have come as an improvement in comparison to legacy diff --git a/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java index 375980312..135497f47 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java @@ -15,20 +15,15 @@ */ package org.springframework.samples.petclinic.owner; -import java.util.Map; - -import javax.validation.Valid; - import org.springframework.samples.petclinic.visit.Visit; import org.springframework.samples.petclinic.visit.VisitRepository; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.InitBinder; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.Map; /** * @author Juergen Hoeller diff --git a/src/main/java/org/springframework/samples/petclinic/system/CacheConfiguration.java b/src/main/java/org/springframework/samples/petclinic/system/CacheConfiguration.java index 0a96582c9..c1da28994 100755 --- a/src/main/java/org/springframework/samples/petclinic/system/CacheConfiguration.java +++ b/src/main/java/org/springframework/samples/petclinic/system/CacheConfiguration.java @@ -16,13 +16,13 @@ package org.springframework.samples.petclinic.system; -import javax.cache.configuration.MutableConfiguration; - import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import javax.cache.configuration.MutableConfiguration; + /** * Cache configuration intended for caches providing the JCache API. This configuration * creates the used cache for the application and enables statistics that become diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java b/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java index ea8ec6ded..3bd2fbe78 100644 --- a/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java +++ b/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java @@ -15,12 +15,11 @@ */ package org.springframework.samples.petclinic.vet; -import java.io.Serializable; +import org.springframework.samples.petclinic.model.NamedEntity; import javax.persistence.Entity; import javax.persistence.Table; - -import org.springframework.samples.petclinic.model.NamedEntity; +import java.io.Serializable; /** * Models a {@link Vet Vet's} specialty (for example, dentistry). diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Vet.java b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java index 014becfce..7f6193102 100644 --- a/src/main/java/org/springframework/samples/petclinic/vet/Vet.java +++ b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java @@ -15,24 +15,14 @@ */ package org.springframework.samples.petclinic.vet; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.Table; -import javax.xml.bind.annotation.XmlElement; - import org.springframework.beans.support.MutableSortDefinition; import org.springframework.beans.support.PropertyComparator; import org.springframework.samples.petclinic.model.Person; +import javax.persistence.*; +import javax.xml.bind.annotation.XmlElement; +import java.util.*; + /** * Simple JavaBean domain object representing a veterinarian. * diff --git a/src/main/java/org/springframework/samples/petclinic/vet/VetController.java b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java index fb5e321ba..170c2e876 100644 --- a/src/main/java/org/springframework/samples/petclinic/vet/VetController.java +++ b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java @@ -15,11 +15,17 @@ */ package org.springframework.samples.petclinic.vet; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; -import java.util.Map; +import java.util.List; /** * @author Juergen Hoeller @@ -37,15 +43,31 @@ class VetController { } @GetMapping("/vets.html") - public String showVetList(Map model) { + public String showVetList(@RequestParam(defaultValue = "1") int page, Model model) { // Here we are returning an object of type 'Vets' rather than a collection of Vet // objects so it is simpler for Object-Xml mapping Vets vets = new Vets(); - vets.getVetList().addAll(this.vets.findAll()); - model.put("vets", vets); + Page paginated = findPaginated(page); + vets.getVetList().addAll(paginated.toList()); + return addPaginationModel(page, paginated, model); + + } + + private String addPaginationModel(int page, Page paginated, Model model) { + List listVets = paginated.getContent(); + model.addAttribute("currentPage", page); + model.addAttribute("totalPages", paginated.getTotalPages()); + model.addAttribute("totalItems", paginated.getTotalElements()); + model.addAttribute("listVets", listVets); return "vets/vetList"; } + private Page findPaginated(int page) { + int pageSize = 5; + Pageable pageable = PageRequest.of(page - 1, pageSize); + return vets.findAll(pageable); + } + @GetMapping({ "/vets" }) public @ResponseBody Vets showResourcesVetList() { // Here we are returning an object of type 'Vets' rather than a collection of Vet diff --git a/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java b/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java index 549b1c229..65af2b86b 100644 --- a/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java @@ -15,13 +15,15 @@ */ package org.springframework.samples.petclinic.vet; -import java.util.Collection; - import org.springframework.cache.annotation.Cacheable; import org.springframework.dao.DataAccessException; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.repository.Repository; import org.springframework.transaction.annotation.Transactional; +import java.util.Collection; + /** * Repository class for Vet domain objects All method names are compliant * with Spring Data naming conventions so this interface can easily be extended for Spring @@ -43,4 +45,16 @@ public interface VetRepository extends Repository { @Cacheable("vets") Collection findAll() throws DataAccessException; + /** + * Retrieve all Vets from data store in Pages + * @param pageable + * @return + * @throws DataAccessException + */ + @Transactional(readOnly = true) + @Cacheable("vets") + Page findAll(Pageable pageable) throws DataAccessException; + + ; + } diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Vets.java b/src/main/java/org/springframework/samples/petclinic/vet/Vets.java index cea665629..961e5c096 100644 --- a/src/main/java/org/springframework/samples/petclinic/vet/Vets.java +++ b/src/main/java/org/springframework/samples/petclinic/vet/Vets.java @@ -15,11 +15,10 @@ */ package org.springframework.samples.petclinic.vet; -import java.util.ArrayList; -import java.util.List; - import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.List; /** * Simple domain object representing a list of veterinarians. Mostly here to be used for diff --git a/src/main/java/org/springframework/samples/petclinic/visit/Visit.java b/src/main/java/org/springframework/samples/petclinic/visit/Visit.java index df9f25fe0..239d60597 100755 --- a/src/main/java/org/springframework/samples/petclinic/visit/Visit.java +++ b/src/main/java/org/springframework/samples/petclinic/visit/Visit.java @@ -15,15 +15,14 @@ */ package org.springframework.samples.petclinic.visit; -import java.time.LocalDate; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.samples.petclinic.model.BaseEntity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; import javax.validation.constraints.NotEmpty; - -import org.springframework.format.annotation.DateTimeFormat; -import org.springframework.samples.petclinic.model.BaseEntity; +import java.time.LocalDate; /** * Simple JavaBean domain object representing a visit. diff --git a/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java b/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java index d5a3334c6..4af5079a0 100644 --- a/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java @@ -15,12 +15,12 @@ */ package org.springframework.samples.petclinic.visit; -import java.util.List; - import org.springframework.dao.DataAccessException; import org.springframework.data.repository.Repository; import org.springframework.samples.petclinic.model.BaseEntity; +import java.util.List; + /** * Repository class for Visit domain objects All method names are compliant * with Spring Data naming conventions so this interface can easily be extended for Spring diff --git a/src/main/resources/templates/owners/ownersList.html b/src/main/resources/templates/owners/ownersList.html index 55cbe0a6a..9d5a9aaab 100644 --- a/src/main/resources/templates/owners/ownersList.html +++ b/src/main/resources/templates/owners/ownersList.html @@ -2,32 +2,61 @@ - + -

Owners

+

Owners

- - - - - - - - - - - - - - - - -
NameAddressCityTelephonePets
- - - - -
- - + + + + + + + + + + + + + + + + +
NameAddressCityTelephonePets
+ + + + +
+
+ Pages: + [ + + [[${i}]] + [[${i}]] + + + + + + + + + + + + + + + + + + +
+ + diff --git a/src/main/resources/templates/vets/vetList.html b/src/main/resources/templates/vets/vetList.html index 4fc961793..26432ed8f 100644 --- a/src/main/resources/templates/vets/vetList.html +++ b/src/main/resources/templates/vets/vetList.html @@ -1,27 +1,57 @@ + th:replace="~{fragments/layout :: layout (~{::body},'vets')}"> -

Veterinarians

+

Veterinarians

- - - - - - - - - - - - - -
NameSpecialties
none
+ + + + + + + + + + + + + +
NameSpecialties
none
+ +
+ Pages: + [ + + [[${i}]] + [[${i}]] + + + + + + + + + + + + + + + + + + +
diff --git a/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java b/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java index 8d754900d..5fee8191a 100644 --- a/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java +++ b/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java @@ -16,16 +16,15 @@ package org.springframework.samples.petclinic.model; -import java.util.Locale; -import java.util.Set; - -import javax.validation.ConstraintViolation; -import javax.validation.Validator; - import org.junit.jupiter.api.Test; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; +import javax.validation.ConstraintViolation; +import javax.validation.Validator; +import java.util.Locale; +import java.util.Set; + import static org.assertj.core.api.Assertions.assertThat; /** diff --git a/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java index 1d6249c5d..ce6395d7b 100644 --- a/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java @@ -16,32 +16,34 @@ package org.springframework.samples.petclinic.owner; -import java.time.LocalDate; -import java.util.Collections; -import java.util.List; - import org.assertj.core.util.Lists; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.samples.petclinic.visit.Visit; import org.springframework.samples.petclinic.visit.VisitRepository; import org.springframework.test.web.servlet.MockMvc; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.hasProperty; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; +import java.time.LocalDate; +import java.util.Collections; +import java.util.List; + +import static org.hamcrest.Matchers.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.BDDMockito.given; 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.model; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; /** * Test class for {@link OwnerController} @@ -81,10 +83,17 @@ class OwnerControllerTests { max.setName("Max"); max.setBirthDate(LocalDate.now()); george.setPetsInternal(Collections.singleton(max)); + + given(this.owners.findByLastName(eq("Franklin"), any(Pageable.class))) + .willReturn(new PageImpl(Lists.newArrayList(george))); + + given(this.owners.findAll(any(Pageable.class))).willReturn(new PageImpl(Lists.newArrayList(george))); + given(this.owners.findById(TEST_OWNER_ID)).willReturn(george); Visit visit = new Visit(); visit.setDate(LocalDate.now()); given(this.visits.findByPetId(max.getId())).willReturn(Collections.singletonList(visit)); + } @Test @@ -118,23 +127,35 @@ class OwnerControllerTests { @Test void testProcessFindFormSuccess() throws Exception { - given(this.owners.findByLastName("")).willReturn(Lists.newArrayList(george, new Owner())); - mockMvc.perform(get("/owners")).andExpect(status().isOk()).andExpect(view().name("owners/ownersList")); + Page tasks = Mockito.mock(Page.class); + Mockito.when(this.owners.findByLastName(anyString(), org.mockito.Matchers.isA(Pageable.class))) + .thenReturn(tasks); + mockMvc.perform(get("/owners?page=1")).andExpect(status().isOk()).andExpect(view().name("owners/ownersList")); } @Test void testProcessFindFormByLastName() throws Exception { - given(this.owners.findByLastName(george.getLastName())).willReturn(Lists.newArrayList(george)); - mockMvc.perform(get("/owners").param("lastName", "Franklin")).andExpect(status().is3xxRedirection()) + + Page tasks = new PageImpl(Lists.newArrayList(george)); + String lastName = george.getLastName(); + Mockito.when(this.owners.findByLastName(eq("Franklin"), any(Pageable.class))).thenReturn(tasks); + mockMvc.perform(get("/owners?page=1").param("lastName", "Franklin")).andExpect(status().is3xxRedirection()) .andExpect(view().name("redirect:/owners/" + TEST_OWNER_ID)); } @Test void testProcessFindFormNoOwnersFound() throws Exception { - mockMvc.perform(get("/owners").param("lastName", "Unknown Surname")).andExpect(status().isOk()) + int pageNumber = 0; + int pageSize = 1, size = 0; + Pageable pageable = PageRequest.of(pageNumber, pageSize); + Page tasks = new PageImpl(Lists.newArrayList()); + Mockito.when(this.owners.findByLastName(eq("Unknown Surname"), org.mockito.Matchers.isA(Pageable.class))) + .thenReturn(tasks); + mockMvc.perform(get("/owners?page=1").param("lastName", "Unknown Surname")).andExpect(status().isOk()) .andExpect(model().attributeHasFieldErrors("owner", "lastName")) .andExpect(model().attributeHasFieldErrorCode("owner", "lastName", "notFound")) .andExpect(view().name("owners/findOwners")); + } @Test diff --git a/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java index 47c444a78..5efd55fad 100755 --- a/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java @@ -16,13 +16,6 @@ package org.springframework.samples.petclinic.owner; -import static org.mockito.BDDMockito.given; -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.model; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; - import org.assertj.core.util.Lists; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -33,6 +26,11 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType; import org.springframework.test.web.servlet.MockMvc; +import static org.mockito.BDDMockito.given; +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.*; + /** * Test class for the {@link PetController} * diff --git a/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java b/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java index adb96b69d..1c0c01b7e 100644 --- a/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java +++ b/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java @@ -16,12 +16,6 @@ package org.springframework.samples.petclinic.owner; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Locale; - import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -29,6 +23,12 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Locale; + import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; diff --git a/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java index 84bee72df..a22317bfe 100644 --- a/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java @@ -16,13 +16,6 @@ package org.springframework.samples.petclinic.owner; -import static org.mockito.BDDMockito.given; -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.model; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -31,6 +24,11 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.samples.petclinic.visit.VisitRepository; import org.springframework.test.web.servlet.MockMvc; +import static org.mockito.BDDMockito.given; +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.*; + /** * Test class for {@link VisitController} * diff --git a/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java b/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java index a7f3d9d24..6a133ea23 100644 --- a/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java +++ b/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java @@ -16,20 +16,13 @@ package org.springframework.samples.petclinic.service; -import static org.assertj.core.api.Assertions.assertThat; - -import java.time.LocalDate; -import java.util.Collection; - import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.ComponentScan; -import org.springframework.samples.petclinic.owner.Owner; -import org.springframework.samples.petclinic.owner.OwnerRepository; -import org.springframework.samples.petclinic.owner.Pet; -import org.springframework.samples.petclinic.owner.PetRepository; -import org.springframework.samples.petclinic.owner.PetType; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.samples.petclinic.owner.*; import org.springframework.samples.petclinic.vet.Vet; import org.springframework.samples.petclinic.vet.VetRepository; import org.springframework.samples.petclinic.visit.Visit; @@ -37,6 +30,11 @@ import org.springframework.samples.petclinic.visit.VisitRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDate; +import java.util.Collection; + +import static org.assertj.core.api.Assertions.assertThat; + /** * Integration test of the Service and the Repository layer. *

@@ -48,8 +46,7 @@ import org.springframework.transaction.annotation.Transactional; * time between test execution. *

  • Dependency Injection of test fixture instances, meaning that we * don't need to perform application context lookups. See the use of - * {@link Autowired @Autowired} on the {@link - * ClinicServiceTests#clinicService clinicService} instance variable, which uses + * {@link Autowired @Autowired} on the instance variable, which uses * autowiring by type. *
  • Transaction management, meaning each test method is executed in * its own transaction, which is automatically rolled back by default. Thus, even if tests @@ -81,12 +78,14 @@ class ClinicServiceTests { @Autowired protected VetRepository vets; + Pageable pageable; + @Test void shouldFindOwnersByLastName() { - Collection owners = this.owners.findByLastName("Davis"); + Page owners = this.owners.findByLastName("Davis", pageable); assertThat(owners).hasSize(2); - owners = this.owners.findByLastName("Daviss"); + owners = this.owners.findByLastName("Daviss", pageable); assertThat(owners).isEmpty(); } @@ -102,8 +101,8 @@ class ClinicServiceTests { @Test @Transactional void shouldInsertOwner() { - Collection owners = this.owners.findByLastName("Schultz"); - int found = owners.size(); + Page owners = this.owners.findByLastName("Schultz", pageable); + int found = (int) owners.getTotalElements(); Owner owner = new Owner(); owner.setFirstName("Sam"); @@ -114,8 +113,8 @@ class ClinicServiceTests { this.owners.save(owner); assertThat(owner.getId().longValue()).isNotEqualTo(0); - owners = this.owners.findByLastName("Schultz"); - assertThat(owners.size()).isEqualTo(found + 1); + owners = this.owners.findByLastName("Schultz", pageable); + assertThat(owners.getTotalElements()).isEqualTo(found + 1); } @Test diff --git a/src/test/java/org/springframework/samples/petclinic/service/EntityUtils.java b/src/test/java/org/springframework/samples/petclinic/service/EntityUtils.java index ca8bc41fc..7b7a5e64a 100644 --- a/src/test/java/org/springframework/samples/petclinic/service/EntityUtils.java +++ b/src/test/java/org/springframework/samples/petclinic/service/EntityUtils.java @@ -16,11 +16,11 @@ package org.springframework.samples.petclinic.service; -import java.util.Collection; - import org.springframework.orm.ObjectRetrievalFailureException; import org.springframework.samples.petclinic.model.BaseEntity; +import java.util.Collection; + /** * Utility methods for handling entities. Separate from the BaseEntity class mainly * because of dependency on the ORM-associated ObjectRetrievalFailureException. diff --git a/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java b/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java index 6bafc7499..06e714085 100644 --- a/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java @@ -23,10 +23,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; /** * Test class for {@link CrashController} diff --git a/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java b/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java index fd537bee2..e0b4964be 100644 --- a/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java @@ -16,27 +16,28 @@ package org.springframework.samples.petclinic.vet; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; - import org.assertj.core.util.Lists; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; /** * Test class for the {@link VetController} */ + @WebMvcTest(VetController.class) class VetControllerTests { @@ -46,13 +47,17 @@ class VetControllerTests { @MockBean private VetRepository vets; + private Vet james; + + private Vet helen; + @BeforeEach void setup() { - Vet james = new Vet(); + james = new Vet(); james.setFirstName("James"); james.setLastName("Carter"); james.setId(1); - Vet helen = new Vet(); + helen = new Vet(); helen.setFirstName("Helen"); helen.setLastName("Leary"); helen.setId(2); @@ -61,12 +66,16 @@ class VetControllerTests { radiology.setName("radiology"); helen.addSpecialty(radiology); given(this.vets.findAll()).willReturn(Lists.newArrayList(james, helen)); + given(this.vets.findAll(any(Pageable.class))).willReturn(new PageImpl(Lists.newArrayList(james, helen))); + } @Test void testShowVetListHtml() throws Exception { - mockMvc.perform(get("/vets.html")).andExpect(status().isOk()).andExpect(model().attributeExists("vets")) - .andExpect(view().name("vets/vetList")); + + mockMvc.perform(MockMvcRequestBuilders.get("/vets.html?page=1")).andExpect(status().isOk()) + .andExpect(model().attributeExists("listVets")).andExpect(view().name("vets/vetList")); + } @Test