diff --git a/.travis.yml b/.travis.yml index 1e91cb501..3c5914319 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,23 @@ -dist: trusty language: java -jdk: oraclejdk8 +sudo: true +dist: trusty + +# use Java 8 +jdk: openjdk8 + +before_install: + - chmod +x mvnw + +jobs: + include: + - stage: test + script: ./mvnw clean test + - stage: verify + script: ./mvnw verify + +cache: + directories: + - $HOME/.m2 + +notifications: +# email: email@provider.com diff --git a/src/main/java/org/springframework/samples/petclinic/controller/OwnerController.java b/src/main/java/org/springframework/samples/petclinic/controller/OwnerController.java index 6cfcec4ef..23d0959ef 100644 --- a/src/main/java/org/springframework/samples/petclinic/controller/OwnerController.java +++ b/src/main/java/org/springframework/samples/petclinic/controller/OwnerController.java @@ -71,7 +71,7 @@ class OwnerController { return CommonView.OWNER_CREATE_OR_UPDATE; } else { - this.ownerService.save(owner); + owner = this.ownerService.save(owner); return CommonView.OWNER_OWNERS_R + owner.getId(); } } diff --git a/src/main/java/org/springframework/samples/petclinic/dto/PetTypeDTO.java b/src/main/java/org/springframework/samples/petclinic/dto/PetTypeDTO.java index 100c134bc..12998ba83 100644 --- a/src/main/java/org/springframework/samples/petclinic/dto/PetTypeDTO.java +++ b/src/main/java/org/springframework/samples/petclinic/dto/PetTypeDTO.java @@ -7,6 +7,10 @@ package org.springframework.samples.petclinic.dto; */ public class PetTypeDTO extends NamedDTO { + public PetTypeDTO() { + super(); + } + @Override public boolean equals(Object obj) { return super.equals(obj); diff --git a/src/main/java/org/springframework/samples/petclinic/dto/VisitDTO.java b/src/main/java/org/springframework/samples/petclinic/dto/VisitDTO.java index 9f89a6bcf..f12d0f9a9 100644 --- a/src/main/java/org/springframework/samples/petclinic/dto/VisitDTO.java +++ b/src/main/java/org/springframework/samples/petclinic/dto/VisitDTO.java @@ -27,14 +27,12 @@ import java.time.LocalDate; */ public class VisitDTO extends BaseDTO { - @NotNull @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate date; @NotEmpty private String description; - @NotNull private Integer petId; /** 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 bc5f2df92..0c2453dc5 100644 --- a/src/main/java/org/springframework/samples/petclinic/model/Owner.java +++ b/src/main/java/org/springframework/samples/petclinic/model/Owner.java @@ -104,9 +104,20 @@ public class Owner extends Person { } public void addPet(Pet pet) { - if (!this.getPets().contains(pet)) { - getPetsInternal().add(pet); + + if (this.pets == null) { + } + try { + if (!this.getPets().contains(pet)) { + getPetsInternal().add(pet); + } + } + catch (Exception exception) { + this.pets = new HashSet<>(); + this.pets.add(pet); + } + pet.setOwner(this); } diff --git a/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java index 14cc90528..fe1a248b5 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java @@ -68,6 +68,6 @@ public interface OwnerRepository extends Repository { * Save an {@link Owner} to the data store, either inserting or updating it. * @param owner the {@link Owner} to save */ - void save(Owner owner); + Owner save(Owner owner); } diff --git a/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java index 1d52108c9..48b975bdf 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java @@ -69,6 +69,6 @@ public interface PetRepository extends Repository { * Save a {@link Pet} to the data store, either inserting or updating it. * @param pet the {@link Pet} to save */ - void save(Pet pet); + Pet save(Pet pet); } diff --git a/src/main/java/org/springframework/samples/petclinic/repository/PetTypeRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/PetTypeRepository.java index 77eb7e6b3..5843e1719 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/PetTypeRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/PetTypeRepository.java @@ -46,6 +46,6 @@ public interface PetTypeRepository extends Repository { * Save a {@link PetType} to the data store, either inserting or updating it. * @param petType the {@link PetType} to save */ - void save(PetType petType); + PetType save(PetType petType); } diff --git a/src/main/java/org/springframework/samples/petclinic/repository/SpecialtyRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/SpecialtyRepository.java index 327161809..dd78d06c4 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/SpecialtyRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/SpecialtyRepository.java @@ -47,6 +47,6 @@ public interface SpecialtyRepository extends Repository { * Save a {@link Specialty} to the data store, either inserting or updating it. * @param specialty the {@link Specialty} to save */ - void save(Specialty specialty); + Specialty save(Specialty specialty); } diff --git a/src/main/java/org/springframework/samples/petclinic/repository/VetRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/VetRepository.java index ae585f19f..af0a758d2 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/VetRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/VetRepository.java @@ -55,6 +55,6 @@ public interface VetRepository extends Repository { * Save a {@link Vet} to the data store, either inserting or updating it. * @param vet the {@link Vet} to save */ - void save(Vet vet); + Vet save(Vet vet); } diff --git a/src/main/java/org/springframework/samples/petclinic/repository/VisitRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/VisitRepository.java index 06fe23dd8..534f2599c 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/VisitRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/VisitRepository.java @@ -41,7 +41,7 @@ public interface VisitRepository extends Repository { * @param visit the Visit to save * @see BaseEntity#isNew */ - void save(Visit visit); + Visit save(Visit visit); /** * Retrieve a {@link Visit} from the data store by id. diff --git a/src/main/java/org/springframework/samples/petclinic/service/BaseService.java b/src/main/java/org/springframework/samples/petclinic/service/BaseService.java index 5b4cdf5de..3578d4ab2 100644 --- a/src/main/java/org/springframework/samples/petclinic/service/BaseService.java +++ b/src/main/java/org/springframework/samples/petclinic/service/BaseService.java @@ -19,7 +19,7 @@ public interface BaseService { /** * Convert Entity Model to Data Transfert Object * @param entity Entity Model - * @return DTO + * @return DTO object */ D entityToDTO(E entity); @@ -40,19 +40,20 @@ public interface BaseService { /** * Get DTO object from repository by his ID * @param id identify object to be found - * @return + * @return DTO object */ D findById(int id); /** * Get all DTO objects from repository - * @return + * @return all DTO objects */ List findAll(); /** * Save DTO object to repository + * @return saved DTO object */ - void save(D dto); + D save(D dto); } diff --git a/src/main/java/org/springframework/samples/petclinic/service/OwnerService.java b/src/main/java/org/springframework/samples/petclinic/service/OwnerService.java index 675b7b639..5a783acca 100644 --- a/src/main/java/org/springframework/samples/petclinic/service/OwnerService.java +++ b/src/main/java/org/springframework/samples/petclinic/service/OwnerService.java @@ -90,18 +90,45 @@ public class OwnerService implements BaseService { @Override public OwnerDTO findById(int ownerId) { Owner owner = ownerRepository.findById(ownerId); + List pets = petRepository.findByOwnerId(owner.getId()); + + pets.forEach(pet -> { + // Add pet to the owner + owner.addPet(pet); + // Add owner to the pet + pet.setOwner(owner); + }); + return entityToDTO(owner); } @Override public List findAll() { - return entitiesToDTOS(ownerRepository.findAll()); + List owners = ownerRepository.findAll(); + + // Add pets for each owners + owners.forEach(owner -> { + + // Find owner pets + List pets = petRepository.findByOwnerId(owner.getId()); + + pets.forEach(pet -> { + // Add pet to the owner + owner.addPet(pet); + // Add owner to the pet + pet.setOwner(owner); + }); + }); + + return entitiesToDTOS(owners); } @Override - public void save(OwnerDTO ownerDTO) { + public OwnerDTO save(OwnerDTO ownerDTO) { Owner owner = dtoToEntity(ownerDTO); - ownerRepository.save(owner); + owner = ownerRepository.save(owner); + + return entityToDTO(owner); } public List findByLastName(String lastName) { diff --git a/src/main/java/org/springframework/samples/petclinic/service/PetService.java b/src/main/java/org/springframework/samples/petclinic/service/PetService.java index 20c74b15d..ddd85a771 100644 --- a/src/main/java/org/springframework/samples/petclinic/service/PetService.java +++ b/src/main/java/org/springframework/samples/petclinic/service/PetService.java @@ -45,6 +45,7 @@ public class PetService implements BaseService { public Pet dtoToEntity(PetDTO dto) { if (dto != null) { Pet pet = modelMapper.map(dto, Pet.class); + PetType petType = modelMapper.map(dto.getType(), PetType.class); Owner owner = modelMapper.map(dto.getOwner(), Owner.class); dto.getVisits().forEach(visitDTO -> pet.addVisit(visitService.dtoToEntity(visitDTO))); @@ -60,6 +61,7 @@ public class PetService implements BaseService { } }); pet.setOwner(owner); + pet.setType(petType); return pet; } @@ -70,6 +72,7 @@ public class PetService implements BaseService { public PetDTO entityToDTO(Pet entity) { if (entity != null) { PetDTO petDTO = modelMapper.map(entity, PetDTO.class); + PetTypeDTO petTypeDTO = modelMapper.map(entity.getType(), PetTypeDTO.class); OwnerDTO ownerDTO = modelMapper.map(entity.getOwner(), OwnerDTO.class); petRepository.findByOwnerId(ownerDTO.getId()).forEach(pet -> { @@ -81,6 +84,7 @@ public class PetService implements BaseService { entity.getVisits().forEach(visit -> petDTO.addVisit(visitService.entityToDTO(visit))); petDTO.setOwner(ownerDTO); + petDTO.setType(petTypeDTO); return petDTO; } @@ -117,8 +121,11 @@ public class PetService implements BaseService { } @Override - public void save(PetDTO petDTO) { - petRepository.save(dtoToEntity(petDTO)); + public PetDTO save(PetDTO petDTO) { + Pet pet = dtoToEntity(petDTO); + pet = petRepository.save(pet); + + return entityToDTO(pet); } public List findByOwnerId(int id) { diff --git a/src/main/java/org/springframework/samples/petclinic/service/PetTypeService.java b/src/main/java/org/springframework/samples/petclinic/service/PetTypeService.java index 23c97f0a9..79ab94a07 100644 --- a/src/main/java/org/springframework/samples/petclinic/service/PetTypeService.java +++ b/src/main/java/org/springframework/samples/petclinic/service/PetTypeService.java @@ -72,8 +72,10 @@ public class PetTypeService implements BaseService { } @Override - public void save(PetTypeDTO dto) { - petTypeRepository.save(dtoToEntity(dto)); + public PetTypeDTO save(PetTypeDTO dto) { + PetType petType = dtoToEntity(dto); + petType = petTypeRepository.save(petType); + return entityToDTO(petType); } } diff --git a/src/main/java/org/springframework/samples/petclinic/service/SpecialtyService.java b/src/main/java/org/springframework/samples/petclinic/service/SpecialtyService.java index d4eb07cb8..3afbb87e4 100644 --- a/src/main/java/org/springframework/samples/petclinic/service/SpecialtyService.java +++ b/src/main/java/org/springframework/samples/petclinic/service/SpecialtyService.java @@ -74,8 +74,11 @@ public class SpecialtyService implements BaseService { } @Override - public void save(SpecialtyDTO dto) { - specialtyRepository.save(dtoToEntity(dto)); + public SpecialtyDTO save(SpecialtyDTO dto) { + Specialty specialty = dtoToEntity(dto); + specialty = specialtyRepository.save(specialty); + + return entityToDTO(specialty); } } diff --git a/src/main/java/org/springframework/samples/petclinic/service/VetService.java b/src/main/java/org/springframework/samples/petclinic/service/VetService.java index cc1b59d62..3eac5d666 100644 --- a/src/main/java/org/springframework/samples/petclinic/service/VetService.java +++ b/src/main/java/org/springframework/samples/petclinic/service/VetService.java @@ -90,8 +90,11 @@ public class VetService implements BaseService { } @Override - public void save(VetDTO dto) { - vetRepository.save(dtoToEntity(dto)); + public VetDTO save(VetDTO dto) { + Vet vet = dtoToEntity(dto); + vet = vetRepository.save(vet); + + return entityToDTO(vet); } } diff --git a/src/main/java/org/springframework/samples/petclinic/service/VisitService.java b/src/main/java/org/springframework/samples/petclinic/service/VisitService.java index 8f627cf80..b5c4d5c4e 100644 --- a/src/main/java/org/springframework/samples/petclinic/service/VisitService.java +++ b/src/main/java/org/springframework/samples/petclinic/service/VisitService.java @@ -74,9 +74,11 @@ public class VisitService implements BaseService { } @Override - public void save(VisitDTO visitDTO) { + public VisitDTO save(VisitDTO visitDTO) { Visit visit = dtoToEntity(visitDTO); - visitRepository.save(visit); + visit = visitRepository.save(visit); + + return entityToDTO(visit); } public Collection findByPetId(Integer petId) { diff --git a/src/test/java/org/springframework/samples/petclinic/PetclinicIT.java b/src/test/java/org/springframework/samples/petclinic/PetclinicIT.java index 1eaf8a17d..185ca1bf9 100644 --- a/src/test/java/org/springframework/samples/petclinic/PetclinicIT.java +++ b/src/test/java/org/springframework/samples/petclinic/PetclinicIT.java @@ -16,13 +16,11 @@ package org.springframework.samples.petclinic; -import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.samples.petclinic.repository.VetRepository; -@Slf4j @SpringBootTest class PetclinicIT { @@ -31,9 +29,6 @@ class PetclinicIT { @Test void testFindAll() throws Exception { - log.info("==================================================================================================="); - log.info("=== in PetclinicIT ==="); - log.info("==================================================================================================="); vets.findAll(); vets.findAll(); // served from cache } diff --git a/src/test/java/org/springframework/samples/petclinic/controller/OwnerControllerIntegrationTest.java b/src/test/java/org/springframework/samples/petclinic/controller/OwnerControllerIntegrationTest.java index 245242588..0d31f6c67 100644 --- a/src/test/java/org/springframework/samples/petclinic/controller/OwnerControllerIntegrationTest.java +++ b/src/test/java/org/springframework/samples/petclinic/controller/OwnerControllerIntegrationTest.java @@ -1,6 +1,5 @@ package org.springframework.samples.petclinic.controller; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; @@ -13,16 +12,16 @@ import org.springframework.samples.petclinic.dto.OwnerDTO; import org.springframework.samples.petclinic.dto.PetDTO; import org.springframework.samples.petclinic.dto.PetTypeDTO; import org.springframework.samples.petclinic.dto.VisitDTO; -import org.springframework.samples.petclinic.model.Owner; -import org.springframework.samples.petclinic.repository.OwnerRepository; +import org.springframework.samples.petclinic.service.OwnerService; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.ui.Model; -import java.nio.charset.StandardCharsets; import java.time.LocalDate; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Objects; import static org.assertj.core.api.Assertions.assertThat; @@ -41,7 +40,7 @@ class OwnerControllerIntegrationTest { private MockMvc mockMvc; @Autowired - private OwnerRepository ownerRepository; + private OwnerService ownerService; static private OwnerDTO george; @@ -67,8 +66,9 @@ class OwnerControllerIntegrationTest { @Test @Tag("initCreationForm") @DisplayName("Verify that the view for new Owner is initialised with new OwnerDTO") - void testInitCreationForm() throws Exception { - final MvcResult result = mockMvc.perform(get(CommonEndPoint.OWNERS_NEW)).andExpect(status().isOk()) + void whenGetNewOwner_thenReturnCreationViewWithNewOwner() throws Exception { + + final MvcResult result = mockMvc.perform(get(CommonEndPoint.OWNERS_NEW)).andExpect(status().is2xxSuccessful()) .andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE)).andReturn(); OwnerDTO found = (OwnerDTO) Objects.requireNonNull(result.getModelAndView()).getModel() @@ -79,46 +79,37 @@ class OwnerControllerIntegrationTest { @Test @Tag("processCreationForm") - void testProcessCreationFormSuccess() throws Exception { - ObjectMapper mapper = new ObjectMapper(); - - String json = mapper.writeValueAsString(george); + void givenNewOwner_whenPostNewOwner_thenSaveOwnerAndRedirectToOwnerView() throws Exception { final MvcResult result = mockMvc .perform(post(CommonEndPoint.OWNERS_NEW).flashAttr(CommonAttribute.OWNER, george)) .andExpect(status().is3xxRedirection()).andReturn(); - json = result.getResponse().getContentAsString(StandardCharsets.UTF_8); - OwnerDTO found = mapper.readValue(json, OwnerDTO.class); + String path = Objects.requireNonNull(result.getModelAndView()).getViewName(); + int ownerId = Integer.parseInt(Objects.requireNonNull(path).split("/")[2]); + OwnerDTO found = ownerService.findById(ownerId); - assertThat(found).isEqualTo(george); + assertThat(found).isEqualToIgnoringGivenFields(george, "id"); } @Test - @Disabled @Tag("processFindForm") @DisplayName("Verify that we get the right view and all Owners") - void testProcessFindFormSuccess() throws Exception { - List expected = ownerRepository.findAll(); + void whenGetFindOwner_thenReturnFindViewWithAllOwners() throws Exception { + List expected = ownerService.findAll(); final MvcResult result = mockMvc.perform(get(CommonEndPoint.OWNERS)) .andExpect(MockMvcResultMatchers.status().isOk()).andExpect(view().name(CommonView.OWNER_OWNERS_LIST)) .andReturn(); - Collection founds = (Collection) result.getModelAndView().getModel() - .get(CommonAttribute.SELECTIONS); + Map model = Objects.requireNonNull(result.getModelAndView()).getModel(); + Collection founds = (Collection) model.get(CommonAttribute.SELECTIONS); int[] position = new int[] { 0 }; - founds.forEach(ownerDTO -> { - Owner owner = expected.get(position[0]++); - - assertThat(owner.getId()).isEqualTo(ownerDTO.getId()); - assertThat(owner.getFirstName()).isEqualTo(ownerDTO.getFirstName()); - assertThat(owner.getLastName()).isEqualTo(ownerDTO.getLastName()); - assertThat(owner.getTelephone()).isEqualTo(ownerDTO.getTelephone()); - assertThat(owner.getAddress()).isEqualTo(ownerDTO.getAddress()); - assertThat(owner.getCity()).isEqualTo(ownerDTO.getCity()); + founds.forEach(found -> { + OwnerDTO owner = expected.get(position[0]++); + assertThat(owner).isEqualToComparingFieldByField(found); }); } diff --git a/src/test/java/org/springframework/samples/petclinic/controller/OwnerControllerTest.java b/src/test/java/org/springframework/samples/petclinic/controller/OwnerControllerTest.java index 3f0c58a16..e003094c4 100644 --- a/src/test/java/org/springframework/samples/petclinic/controller/OwnerControllerTest.java +++ b/src/test/java/org/springframework/samples/petclinic/controller/OwnerControllerTest.java @@ -32,6 +32,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.samples.petclinic.common.CommonAttribute; import org.springframework.samples.petclinic.common.CommonEndPoint; +import org.springframework.samples.petclinic.common.CommonError; import org.springframework.samples.petclinic.common.CommonView; import org.springframework.samples.petclinic.dto.OwnerDTO; import org.springframework.samples.petclinic.dto.PetDTO; @@ -45,6 +46,7 @@ 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 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.request.MockMvcRequestBuilders.post; @@ -61,7 +63,27 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @WebMvcTest(OwnerController.class) class OwnerControllerTest { - private static final int TEST_OWNER_ID = 1; + private static final int OWNER_ID = 15; + + private static final String OWNER_FIRST_NAME = "Joe"; + + private static final String OWNER_LAST_NAME = "BLOGGS"; + + private static final String OWNER_ADDRESS = "123 Caramel Street"; + + private static final String OWNER_CITY = "London"; + + private static final String OWNER_PHONE = "6085551023"; + + private final static Integer PET_ID = 14; + + private final static String PET_NAME = "bowser"; + + private final static LocalDate PET_BIRTH_DATE = LocalDate.of(2020, 7, 11); + + private final static Integer PET_TYPE_ID = 4; + + private final static String PET_TYPE_NAME = "dinausor"; @Autowired private MockMvc mockMvc; @@ -72,153 +94,248 @@ class OwnerControllerTest { @MockBean private VisitService visits; - private OwnerDTO george; + private OwnerDTO ownerDTO; @BeforeEach void setup() { - george = new OwnerDTO(); - george.setId(TEST_OWNER_ID); - george.setFirstName("George"); - george.setLastName("Franklin"); - george.setAddress("110 W. Liberty St."); - george.setCity("Madison"); - george.setTelephone("6085551023"); - PetDTO max = new PetDTO(); - PetTypeDTO dog = new PetTypeDTO(); - dog.setName("dog"); - max.setId(1); - max.setType(dog); - max.setName("Max"); - max.setBirthDate(LocalDate.now()); - george.setPetsInternal(Collections.singleton(max)); - given(this.owners.findById(TEST_OWNER_ID)).willReturn(george); + ownerDTO = new OwnerDTO(); + ownerDTO.setId(OWNER_ID); + ownerDTO.setFirstName(OWNER_FIRST_NAME); + ownerDTO.setLastName(OWNER_LAST_NAME); + ownerDTO.setAddress(OWNER_ADDRESS); + ownerDTO.setCity(OWNER_CITY); + ownerDTO.setTelephone(OWNER_PHONE); + PetDTO petDTO = new PetDTO(); + PetTypeDTO petTypeDTO = new PetTypeDTO(); + petTypeDTO.setId(PET_TYPE_ID); + petTypeDTO.setName(PET_TYPE_NAME); + petDTO.setId(PET_ID); + petDTO.setName(PET_NAME); + petDTO.setType(petTypeDTO); + petDTO.setBirthDate(PET_BIRTH_DATE); + ownerDTO.setPetsInternal(Collections.singleton(petDTO)); + VisitDTO visit = new VisitDTO(); visit.setDate(LocalDate.now()); - given(this.visits.findByPetId(max.getId())).willReturn(Collections.singletonList(visit)); + given(this.owners.findById(OWNER_ID)).willReturn(ownerDTO); + given(this.owners.save(any(OwnerDTO.class))).willReturn(ownerDTO); + given(this.visits.findByPetId(petDTO.getId())).willReturn(Collections.singletonList(visit)); } @Test @Tag("initCreationForm") - @DisplayName("Verify that we get the right view and the right attribute name") - void testInitCreationForm() throws Exception { - mockMvc.perform(get(CommonEndPoint.OWNERS_NEW)).andExpect(status().isOk()) - .andExpect(model().attributeExists(CommonAttribute.OWNER)) + @DisplayName("Verify that we get the right creation view and the right attribute name") + void whenGetNewOwner_thenReturnCreationViewWithNewOwner() throws Exception { + mockMvc.perform(get(CommonEndPoint.OWNERS_NEW)).andExpect(status().is2xxSuccessful()) + .andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE)) + .andExpect(model().attributeExists(CommonAttribute.OWNER)); + } + + @Test + @Tag("processCreationForm") + @DisplayName("Verify that call the right view with parameters when attempt to create Owner") + void givenNewOwner_whenPostNewOwner_thenSaveOwnerAndRedirectToOwnerView() throws Exception { + // Put Owner ID in endpoint + String endPoint = CommonView.OWNER_OWNERS_ID_R.replace("{ownerId}", String.valueOf(OWNER_ID)); + + mockMvc.perform(post(CommonEndPoint.OWNERS_NEW).param(CommonAttribute.OWNER_FIRST_NAME, OWNER_FIRST_NAME) + .param(CommonAttribute.OWNER_LAST_NAME, OWNER_LAST_NAME) + .param(CommonAttribute.OWNER_ADDRESS, OWNER_ADDRESS).param(CommonAttribute.OWNER_CITY, OWNER_CITY) + .param(CommonAttribute.OWNER_PHONE, OWNER_PHONE)).andExpect(status().is3xxRedirection()) + .andExpect(view().name(endPoint)); + } + + @Test + @Tag("processCreationForm") + @DisplayName("Verify that return to Owner creation form when Owner has no firstName") + void givenNewOwnerWithoutFirstName_whenPostNewOwner_thenRedirectToOwnerUpdateView() throws Exception { + + mockMvc.perform(post(CommonEndPoint.OWNERS_NEW).param(CommonAttribute.OWNER_LAST_NAME, OWNER_LAST_NAME) + .param(CommonAttribute.OWNER_ADDRESS, OWNER_ADDRESS).param(CommonAttribute.OWNER_CITY, OWNER_CITY) + .param(CommonAttribute.OWNER_PHONE, OWNER_PHONE)).andExpect(status().isOk()) + .andExpect(model().attributeHasErrors(CommonAttribute.OWNER)) + .andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_FIRST_NAME)) .andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE)); } @Test @Tag("processCreationForm") - void testProcessCreationFormSuccess() throws Exception { - mockMvc.perform(post(CommonEndPoint.OWNERS_NEW).param(CommonAttribute.OWNER_FIRST_NAME, "Joe") - .param(CommonAttribute.OWNER_LAST_NAME, "Bloggs") - .param(CommonAttribute.OWNER_ADDRESS, "123 Caramel Street").param(CommonAttribute.OWNER_CITY, "London") - .param(CommonAttribute.OWNER_PHONE, "01316761638")).andExpect(status().is3xxRedirection()); + @DisplayName("Verify that return to Owner creation form when Owner has no lastName") + void givenNewOwnerWithoutLastName_whenPostNewOwner_thenRedirectToOwnerUpdateView() throws Exception { + + mockMvc.perform(post(CommonEndPoint.OWNERS_NEW).param(CommonAttribute.OWNER_FIRST_NAME, OWNER_FIRST_NAME) + .param(CommonAttribute.OWNER_ADDRESS, OWNER_ADDRESS).param(CommonAttribute.OWNER_CITY, OWNER_CITY) + .param(CommonAttribute.OWNER_PHONE, OWNER_PHONE)).andExpect(status().isOk()) + .andExpect(model().attributeHasErrors(CommonAttribute.OWNER)) + .andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_LAST_NAME)) + .andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE)); } @Test @Tag("processCreationForm") - void testProcessCreationFormHasErrors() throws Exception { - mockMvc.perform(post(CommonEndPoint.OWNERS_NEW).param(CommonAttribute.OWNER_FIRST_NAME, "Joe") - .param(CommonAttribute.OWNER_LAST_NAME, "Bloggs").param(CommonAttribute.OWNER_CITY, "London")) - .andExpect(status().isOk()).andExpect(model().attributeHasErrors(CommonAttribute.OWNER)) + @DisplayName("Verify that return to Owner creation form when Owner has no address") + void givenNewOwnerWithoutAddress_whenPostNewOwner_thenRedirectToOwnerUpdateView() throws Exception { + + mockMvc.perform(post(CommonEndPoint.OWNERS_NEW).param(CommonAttribute.OWNER_FIRST_NAME, OWNER_FIRST_NAME) + .param(CommonAttribute.OWNER_LAST_NAME, OWNER_LAST_NAME).param(CommonAttribute.OWNER_CITY, OWNER_CITY) + .param(CommonAttribute.OWNER_PHONE, OWNER_PHONE)).andExpect(status().isOk()) + .andExpect(model().attributeHasErrors(CommonAttribute.OWNER)) .andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_ADDRESS)) + .andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE)); + } + + @Test + @Tag("processCreationForm") + @DisplayName("Verify that return to Owner creation form when Owner has no phone") + void givenNewOwnerWithoutPhone_whenPostNewOwner_thenRedirectToOwnerUpdateView() throws Exception { + + mockMvc.perform(post(CommonEndPoint.OWNERS_NEW).param(CommonAttribute.OWNER_FIRST_NAME, OWNER_FIRST_NAME) + .param(CommonAttribute.OWNER_LAST_NAME, OWNER_LAST_NAME) + .param(CommonAttribute.OWNER_ADDRESS, OWNER_ADDRESS).param(CommonAttribute.OWNER_CITY, OWNER_CITY)) + .andExpect(status().isOk()).andExpect(model().attributeHasErrors(CommonAttribute.OWNER)) .andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_PHONE)) .andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE)); } @Test @Tag("initFindForm") - void testInitFindForm() throws Exception { - mockMvc.perform(get(CommonEndPoint.OWNERS_FIND)).andExpect(status().isOk()) - .andExpect(model().attributeExists(CommonAttribute.OWNER)) - .andExpect(view().name(CommonView.OWNER_FIND_OWNERS)); + @DisplayName("Verify that we get the right find view and the right attribute name") + void whenGetFindOwner_thenReturnFindViewWithNewOwner() throws Exception { + mockMvc.perform(get(CommonEndPoint.OWNERS_FIND)).andExpect(status().is2xxSuccessful()) + .andExpect(view().name(CommonView.OWNER_FIND_OWNERS)) + .andExpect(model().attributeExists(CommonAttribute.OWNER)); } @Test @Tag("processFindForm") @DisplayName("Verify that we get the right view and all Owners list") - void testProcessFindFormSuccess() throws Exception { - given(this.owners.findByLastName("")).willReturn(Lists.newArrayList(george, new OwnerDTO())); + void whenGetFindOwner_thenReturnFindViewWithAllOwners() throws Exception { + given(this.owners.findByLastName("")).willReturn(Lists.newArrayList(ownerDTO, new OwnerDTO())); - mockMvc.perform(get(CommonEndPoint.OWNERS)).andExpect(status().isOk()) + mockMvc.perform(get(CommonEndPoint.OWNERS)).andExpect(status().is2xxSuccessful()) .andExpect(view().name(CommonView.OWNER_OWNERS_LIST)); } @Test @Tag("processFindForm") - void testProcessFindFormByLastName() throws Exception { - given(this.owners.findByLastName(george.getLastName())).willReturn(Lists.newArrayList(george)); + @DisplayName("Verify that we get the right view and the Owner with specified firstName") + void givenOwnerLastName_whenGetFindOwner_thenReturnViewWithRightOwner() throws Exception { + given(this.owners.findByLastName(ownerDTO.getLastName())).willReturn(Lists.newArrayList(ownerDTO)); - mockMvc.perform(get(CommonEndPoint.OWNERS).param(CommonAttribute.OWNER_LAST_NAME, "Franklin")) - .andExpect(status().is3xxRedirection()) - .andExpect(view().name(CommonView.OWNER_OWNERS_R + TEST_OWNER_ID)); + mockMvc.perform(get(CommonEndPoint.OWNERS).param(CommonAttribute.OWNER_LAST_NAME, OWNER_LAST_NAME)) + .andExpect(status().is3xxRedirection()).andExpect(view().name(CommonView.OWNER_OWNERS_R + OWNER_ID)); } @Test @Tag("processFindForm") - void testProcessFindFormNoOwnersFound() throws Exception { + @DisplayName("Verify that we get empty view and errors with specified wrong firstName") + void givenWrongOwnerLastName_whenGetFindOwner_thenReturnViewWithoutOwner() throws Exception { mockMvc.perform(get(CommonEndPoint.OWNERS).param(CommonAttribute.OWNER_LAST_NAME, "Unknown Surname")) .andExpect(status().isOk()) .andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_LAST_NAME)) .andExpect(model().attributeHasFieldErrorCode(CommonAttribute.OWNER, CommonAttribute.OWNER_LAST_NAME, - "notFound")) + CommonError.NOT_FOUND_ARGS)) .andExpect(view().name(CommonView.OWNER_FIND_OWNERS)); } @Test @Tag("initUpdateOwnerForm") - void testInitUpdateOwnerForm() throws Exception { - mockMvc.perform(get(CommonEndPoint.OWNERS_ID_EDIT, TEST_OWNER_ID)).andExpect(status().isOk()) + @DisplayName("Verify that we get the right update view and the right Owner") + void whenGetUpdateOwner_thenReturnUpdateViewWithRightOwner() throws Exception { + mockMvc.perform(get(CommonEndPoint.OWNERS_ID_EDIT, OWNER_ID)).andExpect(status().isOk()) .andExpect(model().attributeExists(CommonAttribute.OWNER)) .andExpect(model().attribute(CommonAttribute.OWNER, - hasProperty(CommonAttribute.OWNER_LAST_NAME, is("Franklin")))) + hasProperty(CommonAttribute.OWNER_LAST_NAME, is(OWNER_LAST_NAME)))) .andExpect(model().attribute(CommonAttribute.OWNER, - hasProperty(CommonAttribute.OWNER_FIRST_NAME, is("George")))) + hasProperty(CommonAttribute.OWNER_FIRST_NAME, is(OWNER_FIRST_NAME)))) .andExpect(model().attribute(CommonAttribute.OWNER, - hasProperty(CommonAttribute.OWNER_ADDRESS, is("110 W. Liberty St.")))) + hasProperty(CommonAttribute.OWNER_ADDRESS, is(OWNER_ADDRESS)))) .andExpect(model().attribute(CommonAttribute.OWNER, - hasProperty(CommonAttribute.OWNER_CITY, is("Madison")))) + hasProperty(CommonAttribute.OWNER_CITY, is(OWNER_CITY)))) .andExpect(model().attribute(CommonAttribute.OWNER, - hasProperty(CommonAttribute.OWNER_PHONE, is("6085551023")))) + hasProperty(CommonAttribute.OWNER_PHONE, is(OWNER_PHONE)))) .andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE)); } @Test @Tag("processUpdateOwnerForm") - void testProcessUpdateOwnerFormSuccess() throws Exception { - mockMvc.perform(post(CommonEndPoint.OWNERS_ID_EDIT, TEST_OWNER_ID) - .param(CommonAttribute.OWNER_FIRST_NAME, "Joe").param(CommonAttribute.OWNER_LAST_NAME, "Bloggs") - .param(CommonAttribute.OWNER_ADDRESS, "123 Caramel Street").param(CommonAttribute.OWNER_CITY, "London") - .param(CommonAttribute.OWNER_PHONE, "01616291589")).andExpect(status().is3xxRedirection()) - .andExpect(view().name(CommonView.OWNER_OWNERS_ID_R)); + @DisplayName("Verify that call the right view with parameters when attempt to update Owner") + void givenUpdatedOwner_whenPostOwner_thenSaveOwnerAndRedirectToOwnerView() throws Exception { + mockMvc.perform( + post(CommonEndPoint.OWNERS_ID_EDIT, OWNER_ID).param(CommonAttribute.OWNER_FIRST_NAME, OWNER_FIRST_NAME) + .param(CommonAttribute.OWNER_LAST_NAME, OWNER_LAST_NAME) + .param(CommonAttribute.OWNER_ADDRESS, OWNER_ADDRESS) + .param(CommonAttribute.OWNER_CITY, OWNER_CITY).param(CommonAttribute.OWNER_PHONE, OWNER_PHONE)) + .andExpect(status().is3xxRedirection()).andExpect(view().name(CommonView.OWNER_OWNERS_ID_R)); } @Test @Tag("processUpdateOwnerForm") - void testProcessUpdateOwnerFormHasErrors() throws Exception { + @DisplayName("Verify that we return to update view if the Owner firsName is wrong") + void givenUpdatedOwnerWithoutFirstName_whenPostOwner_thenRedirectToUpdateOwnerView() throws Exception { mockMvc.perform( - post(CommonEndPoint.OWNERS_ID_EDIT, TEST_OWNER_ID).param(CommonAttribute.OWNER_FIRST_NAME, "Joe") - .param(CommonAttribute.OWNER_LAST_NAME, "Bloggs").param(CommonAttribute.OWNER_CITY, "London")) + post(CommonEndPoint.OWNERS_ID_EDIT, OWNER_ID).param(CommonAttribute.OWNER_LAST_NAME, OWNER_LAST_NAME) + .param(CommonAttribute.OWNER_ADDRESS, OWNER_ADDRESS) + .param(CommonAttribute.OWNER_CITY, OWNER_CITY).param(CommonAttribute.OWNER_PHONE, OWNER_PHONE)) + .andExpect(status().isOk()).andExpect(model().attributeHasErrors(CommonAttribute.OWNER)) + .andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_FIRST_NAME)) + .andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE)); + } + + @Test + @Tag("processUpdateOwnerForm") + @DisplayName("Verify that we return to update view if the Owner lastName is wrong") + void givenUpdatedOwnerWithoutLastName_whenPostOwner_thenRedirectToUpdateOwnerView() throws Exception { + mockMvc.perform( + post(CommonEndPoint.OWNERS_ID_EDIT, OWNER_ID).param(CommonAttribute.OWNER_FIRST_NAME, OWNER_FIRST_NAME) + .param(CommonAttribute.OWNER_ADDRESS, OWNER_ADDRESS) + .param(CommonAttribute.OWNER_CITY, OWNER_CITY).param(CommonAttribute.OWNER_PHONE, OWNER_PHONE)) + .andExpect(status().isOk()).andExpect(model().attributeHasErrors(CommonAttribute.OWNER)) + .andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_LAST_NAME)) + .andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE)); + } + + @Test + @Tag("processUpdateOwnerForm") + @DisplayName("Verify that we return to update view if the Owner address is wrong") + void givenUpdatedOwnerWithoutAddress_whenPostOwner_thenRedirectToUpdateOwnerView() throws Exception { + mockMvc.perform( + post(CommonEndPoint.OWNERS_ID_EDIT, OWNER_ID).param(CommonAttribute.OWNER_FIRST_NAME, OWNER_FIRST_NAME) + .param(CommonAttribute.OWNER_LAST_NAME, OWNER_LAST_NAME) + .param(CommonAttribute.OWNER_CITY, OWNER_CITY).param(CommonAttribute.OWNER_PHONE, OWNER_PHONE)) .andExpect(status().isOk()).andExpect(model().attributeHasErrors(CommonAttribute.OWNER)) .andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_ADDRESS)) + .andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE)); + } + + @Test + @Tag("processUpdateOwnerForm") + @DisplayName("Verify that we return to update view if the Owner phone is wrong") + void givenUpdatedOwnerWithoutPhone_whenPostOwner_thenRedirectToUpdateOwnerView() throws Exception { + mockMvc.perform(post(CommonEndPoint.OWNERS_ID_EDIT, OWNER_ID) + .param(CommonAttribute.OWNER_FIRST_NAME, OWNER_FIRST_NAME) + .param(CommonAttribute.OWNER_LAST_NAME, OWNER_LAST_NAME) + .param(CommonAttribute.OWNER_ADDRESS, OWNER_ADDRESS).param(CommonAttribute.OWNER_CITY, OWNER_CITY)) + .andExpect(status().isOk()).andExpect(model().attributeHasErrors(CommonAttribute.OWNER)) .andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_PHONE)) .andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE)); } @Test @Tag("processUpdateOwnerForm") - void testShowOwner() throws Exception { - mockMvc.perform(get(CommonEndPoint.OWNERS_ID, TEST_OWNER_ID)).andExpect(status().isOk()) + @DisplayName("Verify that we display view with right Owner") + void givenOwnerId_whenGetOwner_thenShowOwnerView() throws Exception { + mockMvc.perform(get(CommonEndPoint.OWNERS_ID, OWNER_ID)).andExpect(status().isOk()) .andExpect(model().attribute(CommonAttribute.OWNER, - hasProperty(CommonAttribute.OWNER_LAST_NAME, is("Franklin")))) + hasProperty(CommonAttribute.OWNER_LAST_NAME, is(OWNER_LAST_NAME)))) .andExpect(model().attribute(CommonAttribute.OWNER, - hasProperty(CommonAttribute.OWNER_FIRST_NAME, is("George")))) + hasProperty(CommonAttribute.OWNER_FIRST_NAME, is(OWNER_FIRST_NAME)))) .andExpect(model().attribute(CommonAttribute.OWNER, - hasProperty(CommonAttribute.OWNER_ADDRESS, is("110 W. Liberty St.")))) + hasProperty(CommonAttribute.OWNER_ADDRESS, is(OWNER_ADDRESS)))) .andExpect(model().attribute(CommonAttribute.OWNER, - hasProperty(CommonAttribute.OWNER_CITY, is("Madison")))) + hasProperty(CommonAttribute.OWNER_CITY, is(OWNER_CITY)))) .andExpect(model().attribute(CommonAttribute.OWNER, - hasProperty(CommonAttribute.OWNER_PHONE, is("6085551023")))) + hasProperty(CommonAttribute.OWNER_PHONE, is(OWNER_PHONE)))) .andExpect( model().attribute(CommonAttribute.OWNER, hasProperty(CommonAttribute.OWNER_PETS, not(empty())))) .andExpect(model().attribute(CommonAttribute.OWNER, diff --git a/src/test/java/org/springframework/samples/petclinic/controller/PetControllerIntegrationTest.java b/src/test/java/org/springframework/samples/petclinic/controller/PetControllerIntegrationTest.java index eddd6cb60..113c7f16b 100644 --- a/src/test/java/org/springframework/samples/petclinic/controller/PetControllerIntegrationTest.java +++ b/src/test/java/org/springframework/samples/petclinic/controller/PetControllerIntegrationTest.java @@ -10,8 +10,6 @@ import org.springframework.samples.petclinic.common.CommonEndPoint; import org.springframework.samples.petclinic.common.CommonView; import org.springframework.samples.petclinic.dto.OwnerDTO; import org.springframework.samples.petclinic.dto.PetDTO; -import org.springframework.samples.petclinic.dto.PetTypeDTO; -import org.springframework.samples.petclinic.model.PetType; import org.springframework.samples.petclinic.repository.PetRepository; import org.springframework.samples.petclinic.service.OwnerService; import org.springframework.samples.petclinic.service.PetService; @@ -28,6 +26,8 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; /** + * Test class for the {@link PetController} + * * @author Paul-Emmanuel DOS SANTOS FACAO */ @Slf4j @@ -37,7 +37,7 @@ class PetControllerIntegrationTest { private static final int TEST_OWNER_ID = 5; - private static final int TEST_PET_ID = 6; + private static final int PET_ID = 6; @Autowired private MockMvc mockMvc; @@ -57,15 +57,8 @@ class PetControllerIntegrationTest { @BeforeEach void beforeEach() { - ownerDTO = ownerService.findById(TEST_OWNER_ID); - petDTO = new PetDTO(); - PetType type = petRepository.findPetTypes().get(1); - PetTypeDTO typeDTO = new PetTypeDTO(); - typeDTO.setId(type.getId()); - typeDTO.setName(type.getName()); - petDTO.setType(typeDTO); - petDTO.setName("Max"); - petDTO.setBirthDate(LocalDate.now()); + petDTO = petService.findById(PET_ID); + ownerDTO = petDTO.getOwner(); } @Test @@ -104,10 +97,10 @@ class PetControllerIntegrationTest { @Tag("initUpdateForm") @DisplayName("Verify that the view to update Pet is initialised with right Pet") void givenPetId_whenGetUpdatePet_thenReturnUpdateViewWithPet() throws Exception { - PetDTO expected = petService.entityToDTO(petRepository.findById(TEST_PET_ID)); + PetDTO expected = petService.entityToDTO(petRepository.findById(PET_ID)); final MvcResult result = mockMvc - .perform(get(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_ID_EDIT, TEST_OWNER_ID, TEST_PET_ID)) + .perform(get(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_ID_EDIT, ownerDTO.getId(), PET_ID)) .andExpect(status().isOk()).andExpect(model().attributeExists(CommonAttribute.PET)) .andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE)).andReturn(); @@ -120,7 +113,7 @@ class PetControllerIntegrationTest { @Tag("processUpdateForm") @DisplayName("Verify that Pet is updated and the right view is displayed") void givenUpdatePet_whenPostUpdatePet_thenUpdatePetAndRedirectToOwnerView() throws Exception { - PetDTO petExpected = petService.entityToDTO(petRepository.findById(TEST_PET_ID)); + PetDTO petExpected = petService.entityToDTO(petRepository.findById(PET_ID)); OwnerDTO ownerExpected = ownerService.findById(petExpected.getOwner().getId()); petExpected.setName("Nabucho"); petExpected.setBirthDate(LocalDate.now()); @@ -130,7 +123,7 @@ class PetControllerIntegrationTest { .flashAttr(CommonAttribute.OWNER, ownerExpected).flashAttr(CommonAttribute.PET, petExpected)) .andExpect(view().name(CommonView.OWNER_OWNERS_ID_R)).andReturn(); - PetDTO petFound = petService.entityToDTO(petRepository.findById(TEST_PET_ID)); + PetDTO petFound = petService.entityToDTO(petRepository.findById(PET_ID)); assertThat(petFound).isEqualTo(petExpected); } diff --git a/src/test/java/org/springframework/samples/petclinic/controller/PetControllerTest.java b/src/test/java/org/springframework/samples/petclinic/controller/PetControllerTest.java index fc4ed3201..c27ccfcdd 100644 --- a/src/test/java/org/springframework/samples/petclinic/controller/PetControllerTest.java +++ b/src/test/java/org/springframework/samples/petclinic/controller/PetControllerTest.java @@ -88,7 +88,7 @@ class PetControllerTest { @DisplayName("Verify that Pet creation form is initialized") void givenOwnerId_whenAskToCreatePet_thenDisplayCreationViewWithRightPet() throws Exception { mockMvc.perform(get(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID)) - .andExpect(status().isOk()).andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE)) + .andExpect(status().is2xxSuccessful()).andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE)) .andExpect(model().attributeExists(CommonAttribute.PET)); } @@ -105,7 +105,7 @@ class PetControllerTest { @Test @Tag("processCreationForm") @DisplayName("Verify that return to Pet creation form when pet has no name") - void givenNewPetWithoutName_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception { + void givenNewPetWithoutName_whenPostNewPet_thenRedirectToPetUpdate() throws Exception { mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID) .param(CommonAttribute.PET_TYPE, "hamster").param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12")) .andExpect(model().attributeHasNoErrors(CommonAttribute.OWNER)) @@ -119,7 +119,7 @@ class PetControllerTest { @Test @Tag("processCreationForm") @DisplayName("Verify that return to Pet creation form when pet has no type") - void givenNewPetWithoutType_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception { + void givenNewPetWithoutType_whenPostNewPet_thenRedirectToPetUpdate() throws Exception { mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID) .param(CommonAttribute.PET_NAME, "Betty").param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12")) .andExpect(model().attributeHasNoErrors(CommonAttribute.OWNER)) @@ -133,7 +133,7 @@ class PetControllerTest { @Test @Tag("processCreationForm") @DisplayName("Verify that return to Pet creation form when pet has wrong Owner ID") - void givenNewPetWithWrongOwner_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception { + void givenNewPetWithWrongOwner_whenPostNewPet_thenRedirectToPetUpdate() throws Exception { mockMvc.perform( post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, 22).param(CommonAttribute.PET_NAME, "Betty") .param(CommonAttribute.PET_TYPE, "hamster").param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12")) @@ -146,7 +146,7 @@ class PetControllerTest { @Test @Tag("processCreationForm") @DisplayName("Verify that return to Pet creation form when pet has no birth date") - void givenNewPetWithoutBirthDate_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception { + void givenNewPetWithoutBirthDate_whenPostNewPet_thenRedirectToPetUpdate() throws Exception { mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID) .param(CommonAttribute.PET_NAME, "Betty").param(CommonAttribute.PET_TYPE, "hamster")) diff --git a/src/test/java/org/springframework/samples/petclinic/controller/VetControllerIntegrationTest.java b/src/test/java/org/springframework/samples/petclinic/controller/VetControllerIntegrationTest.java index 1ba41c95c..840d84aa6 100644 --- a/src/test/java/org/springframework/samples/petclinic/controller/VetControllerIntegrationTest.java +++ b/src/test/java/org/springframework/samples/petclinic/controller/VetControllerIntegrationTest.java @@ -13,6 +13,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.samples.petclinic.common.CommonAttribute; import org.springframework.samples.petclinic.common.CommonEndPoint; import org.springframework.samples.petclinic.common.CommonView; +import org.springframework.samples.petclinic.dto.VetDTO; import org.springframework.samples.petclinic.dto.VetsDTO; import org.springframework.samples.petclinic.model.Vet; import org.springframework.samples.petclinic.repository.VetRepository; @@ -23,6 +24,7 @@ import org.springframework.test.web.servlet.MvcResult; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Objects; import static org.assertj.core.api.Assertions.assertThat; @@ -48,12 +50,11 @@ class VetControllerIntegrationTest { @Autowired private VetRepository vetRepository; - private VetsDTO expected; + private VetsDTO vetsDTO; @BeforeEach void beforeEach() { - Collection vets = vetRepository.findAll(); - expected = new VetsDTO(vetService.entitiesToDTOS(new ArrayList<>(vets))); + vetsDTO = new VetsDTO(vetService.findAll()); } @Test @@ -67,7 +68,7 @@ class VetControllerIntegrationTest { VetsDTO found = (VetsDTO) Objects.requireNonNull(result.getModelAndView()).getModel().get(CommonAttribute.VETS); - assertThat(found).isEqualToComparingFieldByField(expected); + assertThat(found).isEqualToComparingFieldByField(vetsDTO); } @Test @@ -84,7 +85,7 @@ class VetControllerIntegrationTest { VetsDTO found = mapper.readValue(json, VetsDTO.class); - assertThat(found).isEqualToComparingFieldByField(expected); + assertThat(found).isEqualToComparingFieldByField(vetsDTO); } } diff --git a/src/test/java/org/springframework/samples/petclinic/controller/VisitControllerIntegrationTest.java b/src/test/java/org/springframework/samples/petclinic/controller/VisitControllerIntegrationTest.java index c35e8d3d4..789128026 100644 --- a/src/test/java/org/springframework/samples/petclinic/controller/VisitControllerIntegrationTest.java +++ b/src/test/java/org/springframework/samples/petclinic/controller/VisitControllerIntegrationTest.java @@ -71,7 +71,6 @@ class VisitControllerIntegrationTest { @Tag("initNewVisitForm") @DisplayName("Verify that return form for new Visit with right Pet") void givenPetId_whenGetNewVisit_thenReturnCreationViewWithNewVisit() throws Exception { - Integer nbOfVisits = petDTO.getVisits().size(); final MvcResult result = mockMvc.perform(get(CommonEndPoint.VISITS_NEW, PET_ID)) .andExpect(status().is2xxSuccessful()).andExpect(view().name(CommonView.VISIT_CREATE_OR_UPDATE)) @@ -80,7 +79,6 @@ class VisitControllerIntegrationTest { PetDTO found = (PetDTO) Objects.requireNonNull(result.getModelAndView()).getModel().get(CommonAttribute.PET); assertThat(found).isEqualToIgnoringGivenFields(petDTO, CommonAttribute.VISITS); - assertThat(found.getVisits().size()).isEqualTo(nbOfVisits + 1); VisitDTO expected = new VisitDTO(); expected.setDate(LocalDate.now()); diff --git a/src/test/java/org/springframework/samples/petclinic/service/OwnerServiceTest.java b/src/test/java/org/springframework/samples/petclinic/service/OwnerServiceTest.java index 0857538ab..3cbcc62a3 100644 --- a/src/test/java/org/springframework/samples/petclinic/service/OwnerServiceTest.java +++ b/src/test/java/org/springframework/samples/petclinic/service/OwnerServiceTest.java @@ -8,6 +8,7 @@ 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.common.CommonAttribute; import org.springframework.samples.petclinic.dto.OwnerDTO; import org.springframework.samples.petclinic.dto.PetDTO; import org.springframework.samples.petclinic.dto.PetTypeDTO; @@ -174,7 +175,7 @@ class OwnerServiceTest { List found = ownerService.entitiesToDTOS(owners); - assertThat(found).hasSameSizeAs(expected).containsAll(expected); + assertThat(found).hasSameSizeAs(expected).containsOnlyOnceElementsOf(expected); } @Test @@ -184,7 +185,9 @@ class OwnerServiceTest { List allDTO = ownerService.findAll(); OwnerDTO expected = allDTO.get(2); - assertThat(ownerService.findById(expected.getId())).isEqualTo(expected); + OwnerDTO found = ownerService.findById(expected.getId()); + + assertThat(found).isEqualToComparingFieldByField(expected); } @Test @@ -221,9 +224,10 @@ class OwnerServiceTest { void save() { assertThat(ownerService.findAll()).doesNotContain(ownerDTO); - ownerService.save(ownerDTO); + OwnerDTO saved = ownerService.save(ownerDTO); List found = ownerService.findAll(); + assertThat(saved).isEqualToIgnoringGivenFields(ownerDTO, CommonAttribute.OWNER_ID, CommonAttribute.OWNER_PETS); assertThat(found).usingElementComparatorOnFields("lastName", "firstName", "address", "city", "telephone") .contains(ownerDTO); } diff --git a/src/test/java/org/springframework/samples/petclinic/service/PetServiceTest.java b/src/test/java/org/springframework/samples/petclinic/service/PetServiceTest.java index 62043b9a2..be23962d6 100644 --- a/src/test/java/org/springframework/samples/petclinic/service/PetServiceTest.java +++ b/src/test/java/org/springframework/samples/petclinic/service/PetServiceTest.java @@ -8,6 +8,7 @@ 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.common.CommonAttribute; import org.springframework.samples.petclinic.dto.OwnerDTO; import org.springframework.samples.petclinic.dto.PetDTO; import org.springframework.samples.petclinic.dto.PetTypeDTO; @@ -37,6 +38,10 @@ class PetServiceTest { private final static String PET_BIRTH_DATE = "2020-07-11"; + private final static Integer PET_TYPE_ID = 4; + + private final static String PET_TYPE_NAME = "dinausor"; + @Autowired private OwnerService ownerService; @@ -166,8 +171,9 @@ class PetServiceTest { void save() { assertThat(petService.findAll()).doesNotContain(petDTO); - petService.save(petDTO); + PetDTO saved = petService.save(petDTO); + assertThat(saved).isEqualToIgnoringGivenFields(petDTO, "id"); assertThat(petService.findAll()).containsAnyOf(petDTO); } diff --git a/src/test/java/org/springframework/samples/petclinic/service/VetServiceTest.java b/src/test/java/org/springframework/samples/petclinic/service/VetServiceTest.java index f1c833820..1528f281d 100644 --- a/src/test/java/org/springframework/samples/petclinic/service/VetServiceTest.java +++ b/src/test/java/org/springframework/samples/petclinic/service/VetServiceTest.java @@ -53,7 +53,6 @@ class VetServiceTest { vetDTO.setId(VET_ID); vetDTO.setFirstName(VET_FIRST_NAME); vetDTO.setLastName(VET_LAST_NAME); - } @Test @@ -121,11 +120,11 @@ class VetServiceTest { List expected = vetService.findAll(); assertThat(expected).doesNotContain(vetDTO); - vetService.save(vetDTO); + VetDTO saved = vetService.save(vetDTO); List found = vetService.findAll(); - assertThat(found).contains(vetDTO).containsAll(expected); + assertThat(found).contains(saved).containsAll(expected); } @Test @@ -134,8 +133,9 @@ class VetServiceTest { void save() { assertThat(vetService.findAll()).doesNotContain(vetDTO); - vetService.save(vetDTO); + VetDTO saved = vetService.save(vetDTO); + assertThat(saved).isEqualToIgnoringGivenFields(vetDTO, "id"); assertThat(vetService.findAll()).contains(vetDTO); } diff --git a/src/test/java/org/springframework/samples/petclinic/validator/PetDTOValidatorTest.java b/src/test/java/org/springframework/samples/petclinic/validator/PetDTOValidatorTest.java new file mode 100644 index 000000000..a3e131633 --- /dev/null +++ b/src/test/java/org/springframework/samples/petclinic/validator/PetDTOValidatorTest.java @@ -0,0 +1,111 @@ +package org.springframework.samples.petclinic.validator; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.springframework.samples.petclinic.common.CommonAttribute; +import org.springframework.samples.petclinic.common.CommonError; +import org.springframework.samples.petclinic.dto.PetDTO; +import org.springframework.samples.petclinic.dto.PetTypeDTO; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.Errors; +import org.springframework.validation.FieldError; + +import java.time.LocalDate; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test class for {@link PetDTOValidator} + * + * @author Paul-Emmanuel DOS SANTOS FACAO + */ +class PetDTOValidatorTest { + + private final static Integer PET_ID = 14; + + private final static String PET_NAME = "bowser"; + + private final static String PET_BIRTH_DATE = "2020-07-11"; + + private final static String PET_TYPE_NAME = "dinausaur"; + + private final static Integer PET_TYPE_ID = 11; + + private final PetDTOValidator petDTOValidator = new PetDTOValidator(); + + private PetDTO petDTO; + + @BeforeEach + void beforeEach() { + PetTypeDTO petTypeDTO = new PetTypeDTO(); + petTypeDTO.setId(PET_TYPE_ID); + petTypeDTO.setName(PET_TYPE_NAME); + petDTO = new PetDTO(); + petDTO.setId(PET_ID); + petDTO.setName(PET_NAME); + petDTO.setType(petTypeDTO); + petDTO.setBirthDate(LocalDate.parse(PET_BIRTH_DATE)); + } + + @Test + @Tag("validate") + @DisplayName("Verify that a Pet with good arguments is validate") + void givenRightPetDTO_whenValidate_thenValidate() { + Errors errors = new BeanPropertyBindingResult(petDTO, CommonAttribute.PET); + + petDTOValidator.validate(petDTO, errors); + assertThat(errors.getErrorCount()).isZero(); + } + + @Test + @Tag("validate") + @DisplayName("Verify that a Pet without name is not validate") + void givenPetDTOWithoutName_whenValidate_thenRejectWithError() { + Errors errors = new BeanPropertyBindingResult(petDTO, CommonAttribute.PET); + + petDTO.setName(null); + petDTOValidator.validate(petDTO, errors); + assertThat(errors.getErrorCount()).isEqualTo(1); + FieldError fieldError = errors.getFieldError(CommonAttribute.PET_NAME); + + assertThat(fieldError.getCode()).isEqualTo(CommonError.REQUIRED_ARGS); + assertThat(fieldError.getObjectName()).isEqualTo(CommonAttribute.PET); + assertThat(fieldError.getDefaultMessage()).isEqualTo(CommonError.REQUIRED_MESSAGE); + } + + @Test + @Tag("validate") + @DisplayName("Verify that a Pet without name is not validate") + void givenNewPetDTOWithoutType_whenValidate_thenRejectWithError() { + Errors errors = new BeanPropertyBindingResult(petDTO, CommonAttribute.PET); + + petDTO.setType(null); + petDTO.setId(null); + petDTOValidator.validate(petDTO, errors); + assertThat(errors.getErrorCount()).isEqualTo(1); + + FieldError fieldError = errors.getFieldError(CommonAttribute.PET_TYPE); + assertThat(fieldError.getCode()).isEqualTo(CommonError.REQUIRED_ARGS); + assertThat(fieldError.getObjectName()).isEqualTo(CommonAttribute.PET); + assertThat(fieldError.getDefaultMessage()).isEqualTo(CommonError.REQUIRED_MESSAGE); + } + + @Test + @Tag("validate") + @DisplayName("Verify that a Pet without birthDate is not validate") + void givenNewPetDTOWithoutBirthDateType_whenValidate_thenRejectWithError() { + Errors errors = new BeanPropertyBindingResult(petDTO, CommonAttribute.PET); + + petDTO.setBirthDate(null); + petDTOValidator.validate(petDTO, errors); + assertThat(errors.getErrorCount()).isEqualTo(1); + + FieldError fieldError = errors.getFieldError(CommonAttribute.PET_BIRTH_DATE); + assertThat(fieldError.getCode()).isEqualTo(CommonError.REQUIRED_ARGS); + assertThat(fieldError.getObjectName()).isEqualTo(CommonAttribute.PET); + assertThat(fieldError.getDefaultMessage()).isEqualTo(CommonError.REQUIRED_MESSAGE); + } + +} diff --git a/src/test/java/org/springframework/samples/petclinic/validator/VisitDTOValidatorTest.java b/src/test/java/org/springframework/samples/petclinic/validator/VisitDTOValidatorTest.java new file mode 100644 index 000000000..c60b4ef08 --- /dev/null +++ b/src/test/java/org/springframework/samples/petclinic/validator/VisitDTOValidatorTest.java @@ -0,0 +1,98 @@ +package org.springframework.samples.petclinic.validator; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.springframework.samples.petclinic.common.CommonAttribute; +import org.springframework.samples.petclinic.common.CommonError; +import org.springframework.samples.petclinic.dto.VisitDTO; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.Errors; +import org.springframework.validation.FieldError; +import java.time.LocalDate; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test class for {@link VisitDTOValidator} + * + * @author Paul-Emmanuel DOS SANTOS FACAO + */ +class VisitDTOValidatorTest { + + private final static Integer VISIT_PET_ID = 14; + + private final static String VISIT_DESCRIPTION = "Annual visit for new pet"; + + private final VisitDTOValidator visitDTOValidator = new VisitDTOValidator(); + + private VisitDTO visitDTO; + + @BeforeEach + void beforeEach() { + visitDTO = new VisitDTO(); + visitDTO.setPetId(VISIT_PET_ID); + visitDTO.setDate(LocalDate.now()); + visitDTO.setDescription(VISIT_DESCRIPTION); + } + + @Test + @Tag("validate") + @DisplayName("Verify that a Visit with good arguments is validate") + void givenRightVisitDTO_whenValidate_thenValidate() { + Errors errors = new BeanPropertyBindingResult(visitDTO, CommonAttribute.VISIT); + + visitDTOValidator.validate(visitDTO, errors); + assertThat(errors.getErrorCount()).isZero(); + } + + @Test + @Tag("validate") + @DisplayName("Verify that a Visit without Pet ID is not validate") + void givenVisitDTOWithoutPetID_whenValidate_thenRejectWithError() { + Errors errors = new BeanPropertyBindingResult(visitDTO, CommonAttribute.VISIT); + + visitDTO.setPetId(null); + visitDTOValidator.validate(visitDTO, errors); + assertThat(errors.getErrorCount()).isEqualTo(1); + FieldError fieldError = errors.getFieldError(CommonAttribute.VISIT_PET_ID); + + assertThat(fieldError.getCode()).isEqualTo(CommonError.REQUIRED_ARGS); + assertThat(fieldError.getObjectName()).isEqualTo(CommonAttribute.VISIT); + assertThat(fieldError.getDefaultMessage()).isEqualTo(CommonError.REQUIRED_MESSAGE); + } + + @Test + @Tag("validate") + @DisplayName("Verify that a Visit without date is not validate") + void givenVisitDTOWithoutDate_whenValidate_thenRejectWithError() { + Errors errors = new BeanPropertyBindingResult(visitDTO, CommonAttribute.VISIT); + + visitDTO.setDate(null); + visitDTOValidator.validate(visitDTO, errors); + assertThat(errors.getErrorCount()).isEqualTo(1); + FieldError fieldError = errors.getFieldError(CommonAttribute.VISIT_DATE); + + assertThat(fieldError.getCode()).isEqualTo(CommonError.REQUIRED_ARGS); + assertThat(fieldError.getObjectName()).isEqualTo(CommonAttribute.VISIT); + assertThat(fieldError.getDefaultMessage()).isEqualTo(CommonError.REQUIRED_MESSAGE); + } + + @Test + @Tag("validate") + @DisplayName("Verify that a Visit without description is not validate") + void givenVisitDTOWithoutDescription_whenValidate_thenRejectWithError() { + Errors errors = new BeanPropertyBindingResult(visitDTO, CommonAttribute.VISIT); + + visitDTO.setDescription(null); + visitDTOValidator.validate(visitDTO, errors); + assertThat(errors.getErrorCount()).isEqualTo(1); + FieldError fieldError = errors.getFieldError(CommonAttribute.VISIT_DESCRIPTION); + + assertThat(fieldError.getCode()).isEqualTo(CommonError.REQUIRED_ARGS); + assertThat(fieldError.getObjectName()).isEqualTo(CommonAttribute.VISIT); + assertThat(fieldError.getDefaultMessage()).isEqualTo(CommonError.REQUIRED_MESSAGE); + } + +}