From 874b4af7d8f9f7f5fe52629bc654e536daad2ebd Mon Sep 17 00:00:00 2001 From: "J. A. Parejo" Date: Thu, 13 Feb 2020 00:45:46 +0100 Subject: [PATCH] Fixed tests and separation of services by entity. --- .../samples/petclinic/model/Owner.java | 4 + .../petclinic/service/OwnerService.java | 79 ++++++++++ .../{ClinicService.java => PetService.java} | 55 ++----- .../samples/petclinic/service/VetService.java | 59 ++++++++ .../petclinic/web/OwnerController.java | 19 +-- .../samples/petclinic/web/PetController.java | 26 ++-- .../petclinic/web/PetTypeFormatter.java | 11 +- .../samples/petclinic/web/UserController.java | 11 +- .../samples/petclinic/web/VetController.java | 12 +- .../petclinic/web/VisitController.java | 15 +- .../petclinic/service/OwnerServiceTests.java | 139 ++++++++++++++++++ ...ServiceTests.java => PetServiceTests.java} | 118 +++------------ .../petclinic/service/VetServiceTests.java | 93 ++++++++++++ .../petclinic/web/OwnerControllerTests.java | 5 +- .../petclinic/web/PetControllerTests.java | 15 +- .../petclinic/web/PetTypeFormatterTests.java | 5 +- .../petclinic/web/VetControllerTests.java | 4 +- .../petclinic/web/VisitControllerTests.java | 5 +- 18 files changed, 479 insertions(+), 196 deletions(-) create mode 100644 src/main/java/org/springframework/samples/petclinic/service/OwnerService.java rename src/main/java/org/springframework/samples/petclinic/service/{ClinicService.java => PetService.java} (62%) create mode 100644 src/main/java/org/springframework/samples/petclinic/service/VetService.java create mode 100644 src/test/java/org/springframework/samples/petclinic/service/OwnerServiceTests.java rename src/test/java/org/springframework/samples/petclinic/service/{ClinicServiceTests.java => PetServiceTests.java} (58%) create mode 100644 src/test/java/org/springframework/samples/petclinic/service/VetServiceTests.java diff --git a/src/main/java/org/springframework/samples/petclinic/model/Owner.java b/src/main/java/org/springframework/samples/petclinic/model/Owner.java index 09210d05d31..393ac33ab1b 100644 --- a/src/main/java/org/springframework/samples/petclinic/model/Owner.java +++ b/src/main/java/org/springframework/samples/petclinic/model/Owner.java @@ -122,6 +122,10 @@ public void addPet(Pet pet) { getPetsInternal().add(pet); pet.setOwner(this); } + + public boolean removePet(Pet pet) { + return getPetsInternal().remove(pet); + } /** * Return the Pet with the given name, or null if none found for this Owner. diff --git a/src/main/java/org/springframework/samples/petclinic/service/OwnerService.java b/src/main/java/org/springframework/samples/petclinic/service/OwnerService.java new file mode 100644 index 00000000000..73e745095d3 --- /dev/null +++ b/src/main/java/org/springframework/samples/petclinic/service/OwnerService.java @@ -0,0 +1,79 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.samples.petclinic.service; + +import java.util.Collection; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.dao.DataAccessException; +import org.springframework.samples.petclinic.model.Owner; +import org.springframework.samples.petclinic.model.Pet; +import org.springframework.samples.petclinic.model.PetType; +import org.springframework.samples.petclinic.model.Vet; +import org.springframework.samples.petclinic.model.Visit; +import org.springframework.samples.petclinic.repository.OwnerRepository; +import org.springframework.samples.petclinic.repository.PetRepository; +import org.springframework.samples.petclinic.repository.VetRepository; +import org.springframework.samples.petclinic.repository.VisitRepository; +import org.springframework.samples.petclinic.service.exceptions.DuplicatedPetNameException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +/** + * Mostly used as a facade for all Petclinic controllers Also a placeholder + * for @Transactional and @Cacheable annotations + * + * @author Michael Isvy + */ +@Service +public class OwnerService { + + private OwnerRepository ownerRepository; + + @Autowired + private UserService userService; + + @Autowired + private AuthoritiesService authoritiesService; + + @Autowired + public OwnerService(OwnerRepository ownerRepository) { + this.ownerRepository = ownerRepository; + } + + @Transactional(readOnly = true) + public Owner findOwnerById(int id) throws DataAccessException { + return ownerRepository.findById(id); + } + + @Transactional(readOnly = true) + public Collection findOwnerByLastName(String lastName) throws DataAccessException { + return ownerRepository.findByLastName(lastName); + } + + @Transactional + public void saveOwner(Owner owner) throws DataAccessException { + //creating owner + ownerRepository.save(owner); + //creating user + userService.saveUser(owner.getUser()); + //creating authorities + authoritiesService.saveAuthorities(owner.getUser().getUsername(), "owner"); + } + +} diff --git a/src/main/java/org/springframework/samples/petclinic/service/ClinicService.java b/src/main/java/org/springframework/samples/petclinic/service/PetService.java similarity index 62% rename from src/main/java/org/springframework/samples/petclinic/service/ClinicService.java rename to src/main/java/org/springframework/samples/petclinic/service/PetService.java index 1b2196ba620..e7be27a2728 100644 --- a/src/main/java/org/springframework/samples/petclinic/service/ClinicService.java +++ b/src/main/java/org/springframework/samples/petclinic/service/PetService.java @@ -41,28 +41,17 @@ * @author Michael Isvy */ @Service -public class ClinicService { +public class PetService { private PetRepository petRepository; - - private VetRepository vetRepository; - - private OwnerRepository ownerRepository; - - private VisitRepository visitRepository; - @Autowired - private UserService userService; + private VisitRepository visitRepository; - @Autowired - private AuthoritiesService authoritiesService; @Autowired - public ClinicService(PetRepository petRepository, VetRepository vetRepository, OwnerRepository ownerRepository, + public PetService(PetRepository petRepository, VisitRepository visitRepository) { this.petRepository = petRepository; - this.vetRepository = vetRepository; - this.ownerRepository = ownerRepository; this.visitRepository = visitRepository; } @@ -70,27 +59,7 @@ public ClinicService(PetRepository petRepository, VetRepository vetRepository, O public Collection findPetTypes() throws DataAccessException { return petRepository.findPetTypes(); } - - @Transactional(readOnly = true) - public Owner findOwnerById(int id) throws DataAccessException { - return ownerRepository.findById(id); - } - - @Transactional(readOnly = true) - public Collection findOwnerByLastName(String lastName) throws DataAccessException { - return ownerRepository.findByLastName(lastName); - } - - @Transactional - public void saveOwner(Owner owner) throws DataAccessException { - //creating owner - ownerRepository.save(owner); - //creating user - userService.saveUser(owner.getUser()); - //creating authorities - authoritiesService.saveAuthorities(owner.getUser().getUsername(), "owner"); - } - + @Transactional public void saveVisit(Visit visit) throws DataAccessException { visitRepository.save(visit); @@ -101,19 +70,15 @@ public Pet findPetById(int id) throws DataAccessException { return petRepository.findById(id); } - @Transactional + @Transactional(rollbackFor = DuplicatedPetNameException.class) public void savePet(Pet pet) throws DataAccessException, DuplicatedPetNameException { - if (StringUtils.hasLength(pet.getName()) && pet.isNew() && pet.getOwner().getPet(pet.getName(), true) != null) { - throw new DuplicatedPetNameException(); - } - petRepository.save(pet); + Pet otherPet=pet.getOwner().getPet(pet.getName(), true); + if (StringUtils.hasLength(pet.getName()) && (otherPet!= null && otherPet.getId()!=pet.getId())) { + throw new DuplicatedPetNameException(); + }else + petRepository.save(pet); } - @Transactional(readOnly = true) - @Cacheable(value = "vets") - public Collection findVets() throws DataAccessException { - return vetRepository.findAll(); - } public Collection findVisitsByPetId(int petId) { return visitRepository.findByPetId(petId); diff --git a/src/main/java/org/springframework/samples/petclinic/service/VetService.java b/src/main/java/org/springframework/samples/petclinic/service/VetService.java new file mode 100644 index 00000000000..4516fd7380a --- /dev/null +++ b/src/main/java/org/springframework/samples/petclinic/service/VetService.java @@ -0,0 +1,59 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.samples.petclinic.service; + +import java.util.Collection; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.dao.DataAccessException; +import org.springframework.samples.petclinic.model.Owner; +import org.springframework.samples.petclinic.model.Pet; +import org.springframework.samples.petclinic.model.PetType; +import org.springframework.samples.petclinic.model.Vet; +import org.springframework.samples.petclinic.model.Visit; +import org.springframework.samples.petclinic.repository.OwnerRepository; +import org.springframework.samples.petclinic.repository.PetRepository; +import org.springframework.samples.petclinic.repository.VetRepository; +import org.springframework.samples.petclinic.repository.VisitRepository; +import org.springframework.samples.petclinic.service.exceptions.DuplicatedPetNameException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +/** + * Mostly used as a facade for all Petclinic controllers Also a placeholder + * for @Transactional and @Cacheable annotations + * + * @author Michael Isvy + */ +@Service +public class VetService { + + private VetRepository vetRepository; + + + @Autowired + public VetService(VetRepository vetRepository) { + this.vetRepository = vetRepository; + } + + @Transactional(readOnly = true) + public Collection findVets() throws DataAccessException { + return vetRepository.findAll(); + } + +} diff --git a/src/main/java/org/springframework/samples/petclinic/web/OwnerController.java b/src/main/java/org/springframework/samples/petclinic/web/OwnerController.java index be98a5a70c0..952d3b3033a 100644 --- a/src/main/java/org/springframework/samples/petclinic/web/OwnerController.java +++ b/src/main/java/org/springframework/samples/petclinic/web/OwnerController.java @@ -23,7 +23,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.samples.petclinic.model.Owner; import org.springframework.samples.petclinic.service.AuthoritiesService; -import org.springframework.samples.petclinic.service.ClinicService; +import org.springframework.samples.petclinic.service.OwnerService; +import org.springframework.samples.petclinic.service.VetService; import org.springframework.samples.petclinic.service.UserService; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -43,11 +44,11 @@ public class OwnerController { private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm"; - private final ClinicService clinicService; + private final OwnerService ownerService; @Autowired - public OwnerController(ClinicService clinicService, UserService userService, AuthoritiesService authoritiesService) { - this.clinicService = clinicService; + public OwnerController(OwnerService ownerService, UserService userService, AuthoritiesService authoritiesService) { + this.ownerService = ownerService; } @InitBinder @@ -69,7 +70,7 @@ public String processCreationForm(@Valid Owner owner, BindingResult result) { } else { //creating owner, user and authorities - this.clinicService.saveOwner(owner); + this.ownerService.saveOwner(owner); return "redirect:/owners/" + owner.getId(); } @@ -90,7 +91,7 @@ public String processFindForm(Owner owner, BindingResult result, Map results = this.clinicService.findOwnerByLastName(owner.getLastName()); + Collection results = this.ownerService.findOwnerByLastName(owner.getLastName()); if (results.isEmpty()) { // no owners found result.rejectValue("lastName", "notFound", "not found"); @@ -110,7 +111,7 @@ else if (results.size() == 1) { @GetMapping(value = "/owners/{ownerId}/edit") public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) { - Owner owner = this.clinicService.findOwnerById(ownerId); + Owner owner = this.ownerService.findOwnerById(ownerId); model.addAttribute(owner); return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; } @@ -123,7 +124,7 @@ public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result, } else { owner.setId(ownerId); - this.clinicService.saveOwner(owner); + this.ownerService.saveOwner(owner); return "redirect:/owners/{ownerId}"; } } @@ -136,7 +137,7 @@ public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result, @GetMapping("/owners/{ownerId}") public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) { ModelAndView mav = new ModelAndView("owners/ownerDetails"); - mav.addObject(this.clinicService.findOwnerById(ownerId)); + mav.addObject(this.ownerService.findOwnerById(ownerId)); return mav; } diff --git a/src/main/java/org/springframework/samples/petclinic/web/PetController.java b/src/main/java/org/springframework/samples/petclinic/web/PetController.java index 53de47800c3..725b2b48bec 100644 --- a/src/main/java/org/springframework/samples/petclinic/web/PetController.java +++ b/src/main/java/org/springframework/samples/petclinic/web/PetController.java @@ -19,7 +19,7 @@ import org.springframework.samples.petclinic.model.Owner; import org.springframework.samples.petclinic.model.Pet; import org.springframework.samples.petclinic.model.PetType; -import org.springframework.samples.petclinic.service.ClinicService; +import org.springframework.samples.petclinic.service.VetService; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.util.StringUtils; @@ -35,6 +35,8 @@ import org.springframework.beans.BeanUtils; import org.springframework.dao.DataAccessException; import org.springframework.samples.petclinic.model.Visit; +import org.springframework.samples.petclinic.service.OwnerService; +import org.springframework.samples.petclinic.service.PetService; import org.springframework.samples.petclinic.service.exceptions.DuplicatedPetNameException; /** @@ -48,21 +50,23 @@ public class PetController { private static final String VIEWS_PETS_CREATE_OR_UPDATE_FORM = "pets/createOrUpdatePetForm"; - private final ClinicService clinicService; + private final PetService petService; + private final OwnerService ownerService; @Autowired - public PetController(ClinicService clinicService) { - this.clinicService = clinicService; + public PetController(PetService petService, OwnerService ownerService) { + this.petService = petService; + this.ownerService = ownerService; } @ModelAttribute("types") public Collection populatePetTypes() { - return this.clinicService.findPetTypes(); + return this.petService.findPetTypes(); } @ModelAttribute("owner") public Owner findOwner(@PathVariable("ownerId") int ownerId) { - return this.clinicService.findOwnerById(ownerId); + return this.ownerService.findOwnerById(ownerId); } /*@ModelAttribute("pet") @@ -101,8 +105,8 @@ public String processCreationForm(Owner owner, @Valid Pet pet, BindingResult res } else { try{ - owner.addPet(pet); - this.clinicService.savePet(pet); + owner.addPet(pet); + this.petService.savePet(pet); }catch(DuplicatedPetNameException ex){ result.rejectValue("name", "duplicate", "already exists"); return VIEWS_PETS_CREATE_OR_UPDATE_FORM; @@ -113,7 +117,7 @@ public String processCreationForm(Owner owner, @Valid Pet pet, BindingResult res @GetMapping(value = "/pets/{petId}/edit") public String initUpdateForm(@PathVariable("petId") int petId, ModelMap model) { - Pet pet = this.clinicService.findPetById(petId); + Pet pet = this.petService.findPetById(petId); model.put("pet", pet); return VIEWS_PETS_CREATE_OR_UPDATE_FORM; } @@ -135,10 +139,10 @@ public String processUpdateForm(@Valid Pet pet, BindingResult result, Owner owne return VIEWS_PETS_CREATE_OR_UPDATE_FORM; } else { - Pet petToUpdate=this.clinicService.findPetById(petId); + Pet petToUpdate=this.petService.findPetById(petId); BeanUtils.copyProperties(pet, petToUpdate, "id","owner","visits"); try { - this.clinicService.savePet(petToUpdate); + this.petService.savePet(petToUpdate); } catch (DuplicatedPetNameException ex) { result.rejectValue("name", "duplicate", "already exists"); return VIEWS_PETS_CREATE_OR_UPDATE_FORM; diff --git a/src/main/java/org/springframework/samples/petclinic/web/PetTypeFormatter.java b/src/main/java/org/springframework/samples/petclinic/web/PetTypeFormatter.java index ed407af2861..6daac427ac9 100644 --- a/src/main/java/org/springframework/samples/petclinic/web/PetTypeFormatter.java +++ b/src/main/java/org/springframework/samples/petclinic/web/PetTypeFormatter.java @@ -22,7 +22,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.format.Formatter; import org.springframework.samples.petclinic.model.PetType; -import org.springframework.samples.petclinic.service.ClinicService; +import org.springframework.samples.petclinic.service.PetService; +import org.springframework.samples.petclinic.service.VetService; import org.springframework.stereotype.Component; /** @@ -43,11 +44,11 @@ @Component public class PetTypeFormatter implements Formatter { - private final ClinicService clinicService; + private final PetService peService; @Autowired - public PetTypeFormatter(ClinicService clinicService) { - this.clinicService = clinicService; + public PetTypeFormatter(PetService petService) { + this.peService = petService; } @Override @@ -57,7 +58,7 @@ public String print(PetType petType, Locale locale) { @Override public PetType parse(String text, Locale locale) throws ParseException { - Collection findPetTypes = this.clinicService.findPetTypes(); + Collection findPetTypes = this.peService.findPetTypes(); for (PetType type : findPetTypes) { if (type.getName().equals(text)) { return type; diff --git a/src/main/java/org/springframework/samples/petclinic/web/UserController.java b/src/main/java/org/springframework/samples/petclinic/web/UserController.java index 4ad53037357..a1de38ac5e3 100644 --- a/src/main/java/org/springframework/samples/petclinic/web/UserController.java +++ b/src/main/java/org/springframework/samples/petclinic/web/UserController.java @@ -22,7 +22,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.samples.petclinic.model.Owner; import org.springframework.samples.petclinic.service.AuthoritiesService; -import org.springframework.samples.petclinic.service.ClinicService; +import org.springframework.samples.petclinic.service.OwnerService; +import org.springframework.samples.petclinic.service.VetService; import org.springframework.samples.petclinic.service.UserService; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; @@ -40,11 +41,11 @@ public class UserController { private static final String VIEWS_OWNER_CREATE_FORM = "users/createOwnerForm"; - private final ClinicService clinicService; + private final OwnerService ownerService; @Autowired - public UserController(ClinicService clinicService, UserService userService, AuthoritiesService authoritiesService) { - this.clinicService = clinicService; + public UserController(OwnerService clinicService) { + this.ownerService = clinicService; } @InitBinder @@ -66,7 +67,7 @@ public String processCreationForm(@Valid Owner owner, BindingResult result) { } else { //creating owner, user, and authority - this.clinicService.saveOwner(owner); + this.ownerService.saveOwner(owner); return "redirect:/"; } } diff --git a/src/main/java/org/springframework/samples/petclinic/web/VetController.java b/src/main/java/org/springframework/samples/petclinic/web/VetController.java index 7b6ed2058d7..3696f20ab28 100644 --- a/src/main/java/org/springframework/samples/petclinic/web/VetController.java +++ b/src/main/java/org/springframework/samples/petclinic/web/VetController.java @@ -17,7 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.samples.petclinic.model.Vets; -import org.springframework.samples.petclinic.service.ClinicService; +import org.springframework.samples.petclinic.service.VetService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; @@ -33,11 +33,11 @@ @Controller public class VetController { - private final ClinicService clinicService; + private final VetService vetService; @Autowired - public VetController(ClinicService clinicService) { - this.clinicService = clinicService; + public VetController(VetService clinicService) { + this.vetService = clinicService; } @GetMapping(value = { "/vets" }) @@ -46,7 +46,7 @@ public String showVetList(Map model) { // objects // so it is simpler for Object-Xml mapping Vets vets = new Vets(); - vets.getVetList().addAll(this.clinicService.findVets()); + vets.getVetList().addAll(this.vetService.findVets()); model.put("vets", vets); return "vets/vetList"; } @@ -57,7 +57,7 @@ public String showVetList(Map model) { // objects // so it is simpler for JSon/Object mapping Vets vets = new Vets(); - vets.getVetList().addAll(this.clinicService.findVets()); + vets.getVetList().addAll(this.vetService.findVets()); return vets; } diff --git a/src/main/java/org/springframework/samples/petclinic/web/VisitController.java b/src/main/java/org/springframework/samples/petclinic/web/VisitController.java index 53bf292ea5d..0518de9732e 100644 --- a/src/main/java/org/springframework/samples/petclinic/web/VisitController.java +++ b/src/main/java/org/springframework/samples/petclinic/web/VisitController.java @@ -22,7 +22,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.samples.petclinic.model.Pet; import org.springframework.samples.petclinic.model.Visit; -import org.springframework.samples.petclinic.service.ClinicService; +import org.springframework.samples.petclinic.service.PetService; +import org.springframework.samples.petclinic.service.VetService; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; @@ -37,11 +38,11 @@ @Controller public class VisitController { - private final ClinicService clinicService; + private final PetService petService; @Autowired - public VisitController(ClinicService clinicService) { - this.clinicService = clinicService; + public VisitController(PetService petService) { + this.petService = petService; } @InitBinder @@ -59,7 +60,7 @@ public void setAllowedFields(WebDataBinder dataBinder) { */ @ModelAttribute("visit") public Visit loadPetWithVisit(@PathVariable("petId") int petId) { - Pet pet = this.clinicService.findPetById(petId); + Pet pet = this.petService.findPetById(petId); Visit visit = new Visit(); pet.addVisit(visit); return visit; @@ -78,14 +79,14 @@ public String processNewVisitForm(@Valid Visit visit, BindingResult result) { return "pets/createOrUpdateVisitForm"; } else { - this.clinicService.saveVisit(visit); + this.petService.saveVisit(visit); return "redirect:/owners/{ownerId}"; } } @GetMapping(value = "/owners/*/pets/{petId}/visits") public String showVisits(@PathVariable int petId, Map model) { - model.put("visits", this.clinicService.findPetById(petId).getVisits()); + model.put("visits", this.petService.findPetById(petId).getVisits()); return "visitList"; } diff --git a/src/test/java/org/springframework/samples/petclinic/service/OwnerServiceTests.java b/src/test/java/org/springframework/samples/petclinic/service/OwnerServiceTests.java new file mode 100644 index 00000000000..863b3a40ab8 --- /dev/null +++ b/src/test/java/org/springframework/samples/petclinic/service/OwnerServiceTests.java @@ -0,0 +1,139 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.samples.petclinic.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalDate; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +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.dao.DataAccessException; +import org.springframework.samples.petclinic.model.Owner; +import org.springframework.samples.petclinic.model.Pet; +import org.springframework.samples.petclinic.model.PetType; +import org.springframework.samples.petclinic.model.Vet; +import org.springframework.samples.petclinic.model.Visit; +import org.springframework.samples.petclinic.model.User; +import org.springframework.samples.petclinic.model.Authorities; +import org.springframework.samples.petclinic.service.exceptions.DuplicatedPetNameException; +import org.springframework.samples.petclinic.util.EntityUtils; +import org.springframework.stereotype.Service; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.annotation.Transactional; + +/** + * Integration test of the Service and the Repository layer. + *

+ * ClinicServiceSpringDataJpaTests subclasses benefit from the following services provided + * by the Spring TestContext Framework: + *

+ *
    + *
  • Spring IoC container caching which spares us unnecessary set up + * 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 + * OwnerServiceTests#clinicService clinicService} 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 + * insert or otherwise change database state, there is no need for a teardown or cleanup + * script. + *
  • An {@link org.springframework.context.ApplicationContext ApplicationContext} is + * also inherited and can be used for explicit bean lookup if necessary.
  • + *
+ * + * @author Ken Krebs + * @author Rod Johnson + * @author Juergen Hoeller + * @author Sam Brannen + * @author Michael Isvy + * @author Dave Syer + */ + +@DataJpaTest(includeFilters = @ComponentScan.Filter(Service.class)) +class OwnerServiceTests { + @Autowired + protected OwnerService ownerService; + + @Test + void shouldFindOwnersByLastName() { + Collection owners = this.ownerService.findOwnerByLastName("Davis"); + assertThat(owners.size()).isEqualTo(2); + + owners = this.ownerService.findOwnerByLastName("Daviss"); + assertThat(owners.isEmpty()).isTrue(); + } + + @Test + void shouldFindSingleOwnerWithPet() { + Owner owner = this.ownerService.findOwnerById(1); + assertThat(owner.getLastName()).startsWith("Franklin"); + assertThat(owner.getPets().size()).isEqualTo(1); + assertThat(owner.getPets().get(0).getType()).isNotNull(); + assertThat(owner.getPets().get(0).getType().getName()).isEqualTo("cat"); + } + + @Test + @Transactional + public void shouldInsertOwner() { + Collection owners = this.ownerService.findOwnerByLastName("Schultz"); + int found = owners.size(); + + Owner owner = new Owner(); + owner.setFirstName("Sam"); + owner.setLastName("Schultz"); + owner.setAddress("4, Evans Street"); + owner.setCity("Wollongong"); + owner.setTelephone("4444444444"); + User user=new User(); + user.setUsername("Sam"); + user.setPassword("supersecretpassword"); + user.setEnabled(true); + owner.setUser(user); + + this.ownerService.saveOwner(owner); + assertThat(owner.getId().longValue()).isNotEqualTo(0); + + owners = this.ownerService.findOwnerByLastName("Schultz"); + assertThat(owners.size()).isEqualTo(found + 1); + } + + @Test + @Transactional + void shouldUpdateOwner() { + Owner owner = this.ownerService.findOwnerById(1); + String oldLastName = owner.getLastName(); + String newLastName = oldLastName + "X"; + + owner.setLastName(newLastName); + this.ownerService.saveOwner(owner); + + // retrieving new name from database + owner = this.ownerService.findOwnerById(1); + assertThat(owner.getLastName()).isEqualTo(newLastName); + } + + +} diff --git a/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java b/src/test/java/org/springframework/samples/petclinic/service/PetServiceTests.java similarity index 58% rename from src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java rename to src/test/java/org/springframework/samples/petclinic/service/PetServiceTests.java index f6c28f85445..c3d8c8a3ac5 100644 --- a/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java +++ b/src/test/java/org/springframework/samples/petclinic/service/PetServiceTests.java @@ -23,23 +23,18 @@ import java.util.logging.Logger; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; 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.dao.DataAccessException; import org.springframework.samples.petclinic.model.Owner; import org.springframework.samples.petclinic.model.Pet; import org.springframework.samples.petclinic.model.PetType; import org.springframework.samples.petclinic.model.Vet; import org.springframework.samples.petclinic.model.Visit; import org.springframework.samples.petclinic.model.User; -import org.springframework.samples.petclinic.model.Authorities; import org.springframework.samples.petclinic.service.exceptions.DuplicatedPetNameException; import org.springframework.samples.petclinic.util.EntityUtils; import org.springframework.stereotype.Service; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.transaction.annotation.Transactional; /** @@ -73,72 +68,16 @@ */ @DataJpaTest(includeFilters = @ComponentScan.Filter(Service.class)) -class ClinicServiceTests { - - @Autowired - protected ClinicService clinicService; - - @Test - void shouldFindOwnersByLastName() { - Collection owners = this.clinicService.findOwnerByLastName("Davis"); - assertThat(owners.size()).isEqualTo(2); - - owners = this.clinicService.findOwnerByLastName("Daviss"); - assertThat(owners.isEmpty()).isTrue(); - } - - @Test - void shouldFindSingleOwnerWithPet() { - Owner owner = this.clinicService.findOwnerById(1); - assertThat(owner.getLastName()).startsWith("Franklin"); - assertThat(owner.getPets().size()).isEqualTo(1); - assertThat(owner.getPets().get(0).getType()).isNotNull(); - assertThat(owner.getPets().get(0).getType().getName()).isEqualTo("cat"); - } - - @Test - @Transactional - public void shouldInsertOwner() { - Collection owners = this.clinicService.findOwnerByLastName("Schultz"); - int found = owners.size(); - - Owner owner = new Owner(); - owner.setFirstName("Sam"); - owner.setLastName("Schultz"); - owner.setAddress("4, Evans Street"); - owner.setCity("Wollongong"); - owner.setTelephone("4444444444"); - User user=new User(); - user.setUsername("Sam"); - user.setPassword("supersecretpassword"); - user.setEnabled(true); - owner.setUser(user); - - this.clinicService.saveOwner(owner); - assertThat(owner.getId().longValue()).isNotEqualTo(0); - - owners = this.clinicService.findOwnerByLastName("Schultz"); - assertThat(owners.size()).isEqualTo(found + 1); - } - - @Test - @Transactional - void shouldUpdateOwner() { - Owner owner = this.clinicService.findOwnerById(1); - String oldLastName = owner.getLastName(); - String newLastName = oldLastName + "X"; - - owner.setLastName(newLastName); - this.clinicService.saveOwner(owner); - - // retrieving new name from database - owner = this.clinicService.findOwnerById(1); - assertThat(owner.getLastName()).isEqualTo(newLastName); - } +class PetServiceTests { + @Autowired + protected PetService petService; + + @Autowired + protected OwnerService ownerService; @Test void shouldFindPetWithCorrectId() { - Pet pet7 = this.clinicService.findPetById(7); + Pet pet7 = this.petService.findPetById(7); assertThat(pet7.getName()).startsWith("Samantha"); assertThat(pet7.getOwner().getFirstName()).isEqualTo("Jean"); @@ -146,7 +85,7 @@ void shouldFindPetWithCorrectId() { @Test void shouldFindAllPetTypes() { - Collection petTypes = this.clinicService.findPetTypes(); + Collection petTypes = this.petService.findPetTypes(); PetType petType1 = EntityUtils.getById(petTypes, PetType.class, 1); assertThat(petType1.getName()).isEqualTo("cat"); @@ -157,25 +96,25 @@ void shouldFindAllPetTypes() { @Test @Transactional public void shouldInsertPetIntoDatabaseAndGenerateId() { - Owner owner6 = this.clinicService.findOwnerById(6); + Owner owner6 = this.ownerService.findOwnerById(6); int found = owner6.getPets().size(); Pet pet = new Pet(); pet.setName("bowser"); - Collection types = this.clinicService.findPetTypes(); + Collection types = this.petService.findPetTypes(); pet.setType(EntityUtils.getById(types, PetType.class, 2)); pet.setBirthDate(LocalDate.now()); owner6.addPet(pet); assertThat(owner6.getPets().size()).isEqualTo(found + 1); try { - this.clinicService.savePet(pet); + this.petService.savePet(pet); } catch (DuplicatedPetNameException ex) { - Logger.getLogger(ClinicServiceTests.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(PetServiceTests.class.getName()).log(Level.SEVERE, null, ex); } - this.clinicService.saveOwner(owner6); + this.ownerService.saveOwner(owner6); - owner6 = this.clinicService.findOwnerById(6); + owner6 = this.ownerService.findOwnerById(6); assertThat(owner6.getPets().size()).isEqualTo(found + 1); // checks that id has been generated assertThat(pet.getId()).isNotNull(); @@ -184,51 +123,40 @@ public void shouldInsertPetIntoDatabaseAndGenerateId() { @Test @Transactional public void shouldUpdatePetName() throws Exception { - Pet pet7 = this.clinicService.findPetById(7); + Pet pet7 = this.petService.findPetById(7); String oldName = pet7.getName(); String newName = oldName + "X"; pet7.setName(newName); - this.clinicService.savePet(pet7); + this.petService.savePet(pet7); - pet7 = this.clinicService.findPetById(7); + pet7 = this.petService.findPetById(7); assertThat(pet7.getName()).isEqualTo(newName); } - @Test - void shouldFindVets() { - Collection vets = this.clinicService.findVets(); - - Vet vet = EntityUtils.getById(vets, Vet.class, 3); - assertThat(vet.getLastName()).isEqualTo("Douglas"); - assertThat(vet.getNrOfSpecialties()).isEqualTo(2); - assertThat(vet.getSpecialties().get(0).getName()).isEqualTo("dentistry"); - assertThat(vet.getSpecialties().get(1).getName()).isEqualTo("surgery"); - } - @Test @Transactional public void shouldAddNewVisitForPet() { - Pet pet7 = this.clinicService.findPetById(7); + Pet pet7 = this.petService.findPetById(7); int found = pet7.getVisits().size(); Visit visit = new Visit(); pet7.addVisit(visit); visit.setDescription("test"); - this.clinicService.saveVisit(visit); + this.petService.saveVisit(visit); try { - this.clinicService.savePet(pet7); + this.petService.savePet(pet7); } catch (DuplicatedPetNameException ex) { - Logger.getLogger(ClinicServiceTests.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(PetServiceTests.class.getName()).log(Level.SEVERE, null, ex); } - pet7 = this.clinicService.findPetById(7); + pet7 = this.petService.findPetById(7); assertThat(pet7.getVisits().size()).isEqualTo(found + 1); assertThat(visit.getId()).isNotNull(); } @Test void shouldFindVisitsByPetId() throws Exception { - Collection visits = this.clinicService.findVisitsByPetId(7); + Collection visits = this.petService.findVisitsByPetId(7); assertThat(visits.size()).isEqualTo(2); Visit[] visitArr = visits.toArray(new Visit[visits.size()]); assertThat(visitArr[0].getPet()).isNotNull(); diff --git a/src/test/java/org/springframework/samples/petclinic/service/VetServiceTests.java b/src/test/java/org/springframework/samples/petclinic/service/VetServiceTests.java new file mode 100644 index 00000000000..10732a019f6 --- /dev/null +++ b/src/test/java/org/springframework/samples/petclinic/service/VetServiceTests.java @@ -0,0 +1,93 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.samples.petclinic.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalDate; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +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.dao.DataAccessException; +import org.springframework.samples.petclinic.model.Owner; +import org.springframework.samples.petclinic.model.Pet; +import org.springframework.samples.petclinic.model.PetType; +import org.springframework.samples.petclinic.model.Vet; +import org.springframework.samples.petclinic.model.Visit; +import org.springframework.samples.petclinic.model.User; +import org.springframework.samples.petclinic.model.Authorities; +import org.springframework.samples.petclinic.service.exceptions.DuplicatedPetNameException; +import org.springframework.samples.petclinic.util.EntityUtils; +import org.springframework.stereotype.Service; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.annotation.Transactional; + +/** + * Integration test of the Service and the Repository layer. + *

+ * ClinicServiceSpringDataJpaTests subclasses benefit from the following services provided + * by the Spring TestContext Framework: + *

+ *
    + *
  • Spring IoC container caching which spares us unnecessary set up + * 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 + * 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 + * insert or otherwise change database state, there is no need for a teardown or cleanup + * script. + *
  • An {@link org.springframework.context.ApplicationContext ApplicationContext} is + * also inherited and can be used for explicit bean lookup if necessary.
  • + *
+ * + * @author Ken Krebs + * @author Rod Johnson + * @author Juergen Hoeller + * @author Sam Brannen + * @author Michael Isvy + * @author Dave Syer + */ + +@DataJpaTest(includeFilters = @ComponentScan.Filter(Service.class)) +class VetServiceTests { + + @Autowired + protected VetService vetService; + + @Test + void shouldFindVets() { + Collection vets = this.vetService.findVets(); + + Vet vet = EntityUtils.getById(vets, Vet.class, 3); + assertThat(vet.getLastName()).isEqualTo("Douglas"); + assertThat(vet.getNrOfSpecialties()).isEqualTo(2); + assertThat(vet.getSpecialties().get(0).getName()).isEqualTo("dentistry"); + assertThat(vet.getSpecialties().get(1).getName()).isEqualTo("surgery"); + } + + +} diff --git a/src/test/java/org/springframework/samples/petclinic/web/OwnerControllerTests.java b/src/test/java/org/springframework/samples/petclinic/web/OwnerControllerTests.java index 98d1c23f77d..4813861af39 100644 --- a/src/test/java/org/springframework/samples/petclinic/web/OwnerControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/web/OwnerControllerTests.java @@ -6,7 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.samples.petclinic.configuration.SecurityConfiguration; import org.springframework.samples.petclinic.model.Owner; -import org.springframework.samples.petclinic.service.ClinicService; +import org.springframework.samples.petclinic.service.VetService; import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; @@ -19,6 +19,7 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType; import org.springframework.samples.petclinic.service.AuthoritiesService; +import org.springframework.samples.petclinic.service.OwnerService; import org.springframework.samples.petclinic.service.UserService; import org.springframework.security.config.annotation.web.WebSecurityConfigurer; import org.springframework.security.test.context.support.WithMockUser; @@ -44,7 +45,7 @@ class OwnerControllerTests { private OwnerController ownerController; @MockBean - private ClinicService clinicService; + private OwnerService clinicService; @MockBean private UserService userService; diff --git a/src/test/java/org/springframework/samples/petclinic/web/PetControllerTests.java b/src/test/java/org/springframework/samples/petclinic/web/PetControllerTests.java index 04b3fc724f3..8764973e39a 100644 --- a/src/test/java/org/springframework/samples/petclinic/web/PetControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/web/PetControllerTests.java @@ -36,7 +36,9 @@ import org.springframework.samples.petclinic.model.Owner; import org.springframework.samples.petclinic.model.Pet; import org.springframework.samples.petclinic.model.PetType; -import org.springframework.samples.petclinic.service.ClinicService; +import org.springframework.samples.petclinic.service.OwnerService; +import org.springframework.samples.petclinic.service.PetService; +import org.springframework.samples.petclinic.service.VetService; import org.springframework.security.config.annotation.web.WebSecurityConfigurer; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; @@ -61,7 +63,10 @@ class PetControllerTests { @MockBean - private ClinicService clinicService; + private PetService petService; + + @MockBean + private OwnerService ownerService; @Autowired private MockMvc mockMvc; @@ -71,9 +76,9 @@ void setup() { PetType cat = new PetType(); cat.setId(3); cat.setName("hamster"); - given(this.clinicService.findPetTypes()).willReturn(Lists.newArrayList(cat)); - given(this.clinicService.findOwnerById(TEST_OWNER_ID)).willReturn(new Owner()); - given(this.clinicService.findPetById(TEST_PET_ID)).willReturn(new Pet()); + given(this.petService.findPetTypes()).willReturn(Lists.newArrayList(cat)); + given(this.ownerService.findOwnerById(TEST_OWNER_ID)).willReturn(new Owner()); + given(this.petService.findPetById(TEST_PET_ID)).willReturn(new Pet()); } @WithMockUser(value = "spring") diff --git a/src/test/java/org/springframework/samples/petclinic/web/PetTypeFormatterTests.java b/src/test/java/org/springframework/samples/petclinic/web/PetTypeFormatterTests.java index 1b9654da8bc..a90613f154c 100644 --- a/src/test/java/org/springframework/samples/petclinic/web/PetTypeFormatterTests.java +++ b/src/test/java/org/springframework/samples/petclinic/web/PetTypeFormatterTests.java @@ -8,7 +8,7 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.samples.petclinic.model.PetType; -import org.springframework.samples.petclinic.service.ClinicService; +import org.springframework.samples.petclinic.service.VetService; import java.text.ParseException; import java.util.ArrayList; @@ -17,6 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.samples.petclinic.service.PetService; /** * Test class for {@link PetTypeFormatter} @@ -27,7 +28,7 @@ class PetTypeFormatterTests { @Mock - private ClinicService clinicService; + private PetService clinicService; private PetTypeFormatter petTypeFormatter; diff --git a/src/test/java/org/springframework/samples/petclinic/web/VetControllerTests.java b/src/test/java/org/springframework/samples/petclinic/web/VetControllerTests.java index 14c9d6a945e..f648c48ba09 100644 --- a/src/test/java/org/springframework/samples/petclinic/web/VetControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/web/VetControllerTests.java @@ -8,7 +8,7 @@ import org.springframework.samples.petclinic.configuration.SecurityConfiguration; import org.springframework.samples.petclinic.model.Specialty; import org.springframework.samples.petclinic.model.Vet; -import org.springframework.samples.petclinic.service.ClinicService; +import org.springframework.samples.petclinic.service.VetService; import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; @@ -37,7 +37,7 @@ class VetControllerTests { private VetController vetController; @MockBean - private ClinicService clinicService; + private VetService clinicService; @Autowired private MockMvc mockMvc; diff --git a/src/test/java/org/springframework/samples/petclinic/web/VisitControllerTests.java b/src/test/java/org/springframework/samples/petclinic/web/VisitControllerTests.java index cd844f8789a..87451fd9462 100644 --- a/src/test/java/org/springframework/samples/petclinic/web/VisitControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/web/VisitControllerTests.java @@ -16,7 +16,8 @@ import org.springframework.context.annotation.FilterType; import org.springframework.samples.petclinic.configuration.SecurityConfiguration; import org.springframework.samples.petclinic.model.Pet; -import org.springframework.samples.petclinic.service.ClinicService; +import org.springframework.samples.petclinic.service.PetService; +import org.springframework.samples.petclinic.service.VetService; import org.springframework.security.config.annotation.web.WebSecurityConfigurer; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; @@ -37,7 +38,7 @@ class VisitControllerTests { private VisitController visitController; @MockBean - private ClinicService clinicService; + private PetService clinicService; @Autowired private MockMvc mockMvc;