add VisitControllerIntegrationTest

modify VisitControllerTest
Create VisitDTOValidator
This commit is contained in:
PEDSF 2020-10-30 11:57:14 +01:00
parent 6b931913ec
commit 42cb0d6059
12 changed files with 366 additions and 94 deletions

View file

@ -43,6 +43,14 @@ public final class CommonAttribute {
public static final String VISIT = "visit"; public static final String VISIT = "visit";
public static final String VISIT_DATE = "date";
public static final String VISIT_DESCRIPTION = "description";
public static final String VISIT_PET_ID = "petId";
public static final String VISITS = "visits";
private CommonAttribute() { private CommonAttribute() {
throw new IllegalStateException("Utility class"); throw new IllegalStateException("Utility class");
} }

View file

@ -47,7 +47,6 @@ class PetController {
private final PetService petService; private final PetService petService;
@Autowired @Autowired
PetController(OwnerService ownerService, PetService petService, PetTypeService petTypeService) { PetController(OwnerService ownerService, PetService petService, PetTypeService petTypeService) {
this.ownerService = ownerService; this.ownerService = ownerService;
@ -87,14 +86,14 @@ class PetController {
@ModelAttribute(CommonAttribute.PET) @Valid PetDTO pet, BindingResult result, ModelMap model) { @ModelAttribute(CommonAttribute.PET) @Valid PetDTO pet, BindingResult result, ModelMap model) {
if (owner == null) { if (owner == null) {
result.rejectValue(CommonAttribute.OWNER, CommonError.NOT_FOUND_ARGS, CommonError.NOT_FOUND_MESSAGE); result.rejectValue(CommonAttribute.OWNER, CommonError.NOT_FOUND_ARGS, CommonError.NOT_FOUND_MESSAGE);
} else { }
else {
if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null) { if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null) {
result.rejectValue(CommonAttribute.NAME, CommonError.DUPLICATE_ARGS, CommonError.DUPLICATE_MESSAGE); result.rejectValue(CommonAttribute.NAME, CommonError.DUPLICATE_ARGS, CommonError.DUPLICATE_MESSAGE);
} }
owner.addPet(pet); owner.addPet(pet);
} }
if (result.hasErrors()) { if (result.hasErrors()) {
model.put(CommonAttribute.PET, pet); model.put(CommonAttribute.PET, pet);
return CommonView.PET_CREATE_OR_UPDATE; return CommonView.PET_CREATE_OR_UPDATE;

View file

@ -52,7 +52,7 @@ class VetController {
return CommonView.VET_VETS_LIST; return CommonView.VET_VETS_LIST;
} }
@GetMapping({ CommonEndPoint.VETS }) @GetMapping(CommonEndPoint.VETS)
public @ResponseBody VetsDTO showResourcesVetList() { public @ResponseBody VetsDTO showResourcesVetList() {
// Here we are returning an object of type 'Vets' rather than a collection of Vet // Here we are returning an object of type 'Vets' rather than a collection of Vet
// objects so it is simpler for JSon/Object mapping // objects so it is simpler for JSon/Object mapping

View file

@ -26,6 +26,8 @@ import org.springframework.samples.petclinic.dto.PetDTO;
import org.springframework.samples.petclinic.dto.VisitDTO; import org.springframework.samples.petclinic.dto.VisitDTO;
import org.springframework.samples.petclinic.service.PetService; import org.springframework.samples.petclinic.service.PetService;
import org.springframework.samples.petclinic.service.VisitService; import org.springframework.samples.petclinic.service.VisitService;
import org.springframework.samples.petclinic.validator.PetDTOValidator;
import org.springframework.samples.petclinic.validator.VisitDTOValidator;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder;
@ -77,6 +79,11 @@ class VisitController {
return visit; return visit;
} }
@InitBinder("visit")
public void initVisitBinder(WebDataBinder dataBinder) {
dataBinder.setValidator(new VisitDTOValidator());
}
// Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called // Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called
@GetMapping(CommonEndPoint.VISITS_NEW) @GetMapping(CommonEndPoint.VISITS_NEW)
public String initNewVisitForm(@PathVariable("petId") int petId, Map<String, Object> model) { public String initNewVisitForm(@PathVariable("petId") int petId, Map<String, Object> model) {

View file

@ -17,6 +17,7 @@ package org.springframework.samples.petclinic.dto;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.LocalDate; import java.time.LocalDate;
/** /**
@ -26,12 +27,14 @@ import java.time.LocalDate;
*/ */
public class VisitDTO extends BaseDTO { public class VisitDTO extends BaseDTO {
@NotNull
@DateTimeFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate date; private LocalDate date;
@NotEmpty @NotEmpty
private String description; private String description;
@NotNull
private Integer petId; private Integer petId;
/** /**
@ -76,7 +79,8 @@ public class VisitDTO extends BaseDTO {
if (!getDate().equals(visitDTO.getDate())) if (!getDate().equals(visitDTO.getDate()))
return false; return false;
if (!getDescription().equals(visitDTO.getDescription())) if (getDescription() != null ? !getDescription().equals(visitDTO.getDescription())
: visitDTO.getDescription() != null)
return false; return false;
return getPetId().equals(visitDTO.getPetId()); return getPetId().equals(visitDTO.getPetId());
} }

View file

@ -0,0 +1,47 @@
package org.springframework.samples.petclinic.validator;
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.Errors;
import org.springframework.validation.Validator;
/**
* <code>Validator</code> for <code>VisitDTO</code> forms.
* <p>
* We're not using Bean Validation annotations here because it is easier to define such
* validation rule in Java.
* </p>
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public class VisitDTOValidator implements Validator {
@Override
public boolean supports(Class<?> aClass) {
return VisitDTO.class.isAssignableFrom(aClass);
}
@Override
public void validate(Object object, Errors errors) {
VisitDTO visit = (VisitDTO) object;
// Pet ID validation
if (visit.getPetId() == null) {
errors.rejectValue(CommonAttribute.VISIT_PET_ID, CommonError.REQUIRED_ARGS, CommonError.REQUIRED_MESSAGE);
}
// Visit date validation
if (visit.getDate() == null) {
errors.rejectValue(CommonAttribute.VISIT_DATE, CommonError.REQUIRED_ARGS, CommonError.REQUIRED_MESSAGE);
}
// Visit description validation
if (visit.getDescription() == null || visit.getDescription().isEmpty()) {
errors.rejectValue(CommonAttribute.VISIT_DESCRIPTION, CommonError.REQUIRED_ARGS,
CommonError.REQUIRED_MESSAGE);
}
}
}

View file

@ -36,6 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
class PetControllerIntegrationTest { class PetControllerIntegrationTest {
private static final int TEST_OWNER_ID = 5; private static final int TEST_OWNER_ID = 5;
private static final int TEST_PET_ID = 6; private static final int TEST_PET_ID = 6;
@Autowired @Autowired
@ -75,7 +76,8 @@ class PetControllerIntegrationTest {
final MvcResult result = mockMvc final MvcResult result = mockMvc
.perform(get(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID) .perform(get(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID)
.flashAttr(CommonAttribute.OWNER, ownerDTO)) .flashAttr(CommonAttribute.OWNER, ownerDTO))
.andExpect(status().isOk()).andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE)).andReturn(); .andExpect(status().is2xxSuccessful()).andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE))
.andReturn();
PetDTO petFound = (PetDTO) Objects.requireNonNull(result.getModelAndView()).getModel().get(CommonAttribute.PET); PetDTO petFound = (PetDTO) Objects.requireNonNull(result.getModelAndView()).getModel().get(CommonAttribute.PET);
@ -104,9 +106,10 @@ class PetControllerIntegrationTest {
void givenPetId_whenGetUpdatePet_thenReturnUpdateViewWithPet() throws Exception { void givenPetId_whenGetUpdatePet_thenReturnUpdateViewWithPet() throws Exception {
PetDTO expected = petService.entityToDTO(petRepository.findById(TEST_PET_ID)); PetDTO expected = petService.entityToDTO(petRepository.findById(TEST_PET_ID));
final MvcResult result = mockMvc.perform(get(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_ID_EDIT, TEST_OWNER_ID, TEST_PET_ID)) final MvcResult result = mockMvc
.andExpect(status().isOk()).andExpect(model().attributeExists(CommonAttribute.PET)) .perform(get(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_ID_EDIT, TEST_OWNER_ID, TEST_PET_ID))
.andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE)).andReturn(); .andExpect(status().isOk()).andExpect(model().attributeExists(CommonAttribute.PET))
.andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE)).andReturn();
PetDTO petFound = (PetDTO) Objects.requireNonNull(result.getModelAndView()).getModel().get(CommonAttribute.PET); PetDTO petFound = (PetDTO) Objects.requireNonNull(result.getModelAndView()).getModel().get(CommonAttribute.PET);
@ -122,13 +125,14 @@ class PetControllerIntegrationTest {
petExpected.setName("Nabucho"); petExpected.setName("Nabucho");
petExpected.setBirthDate(LocalDate.now()); petExpected.setBirthDate(LocalDate.now());
final MvcResult result = mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_ID_EDIT, ownerExpected.getId(), petExpected.getId()) final MvcResult result = mockMvc.perform(
.flashAttr(CommonAttribute.OWNER, ownerExpected).flashAttr(CommonAttribute.PET, petExpected)) post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_ID_EDIT, ownerExpected.getId(), petExpected.getId())
.andExpect(view().name(CommonView.OWNER_OWNERS_ID_R)) .flashAttr(CommonAttribute.OWNER, ownerExpected).flashAttr(CommonAttribute.PET, petExpected))
.andReturn(); .andExpect(view().name(CommonView.OWNER_OWNERS_ID_R)).andReturn();
PetDTO petFound = petService.entityToDTO(petRepository.findById(TEST_PET_ID)); PetDTO petFound = petService.entityToDTO(petRepository.findById(TEST_PET_ID));
assertThat(petFound).isEqualTo(petExpected); assertThat(petFound).isEqualTo(petExpected);
} }
} }

View file

@ -57,6 +57,7 @@ import org.springframework.test.web.servlet.MockMvc;
class PetControllerTest { class PetControllerTest {
private static final int TEST_OWNER_ID = 1; private static final int TEST_OWNER_ID = 1;
private static final int TEST_PET_ID = 1; private static final int TEST_PET_ID = 1;
@Autowired @Autowired
@ -96,11 +97,9 @@ class PetControllerTest {
@DisplayName("Verify that call the right view with parameters when attempt to create Pet") @DisplayName("Verify that call the right view with parameters when attempt to create Pet")
void givenNewPet_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception { void givenNewPet_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception {
mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID) mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID)
.param(CommonAttribute.PET_NAME, "Betty") .param(CommonAttribute.PET_NAME, "Betty").param(CommonAttribute.PET_TYPE, "hamster")
.param(CommonAttribute.PET_TYPE, "hamster") .param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12")).andExpect(status().is3xxRedirection())
.param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12")) .andExpect(view().name(CommonView.OWNER_OWNERS_ID_R));
.andExpect(status().is3xxRedirection())
.andExpect(view().name(CommonView.OWNER_OWNERS_ID_R));
} }
@Test @Test
@ -108,14 +107,13 @@ class PetControllerTest {
@DisplayName("Verify that return to Pet creation form when pet has no name") @DisplayName("Verify that return to Pet creation form when pet has no name")
void givenNewPetWithoutName_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception { void givenNewPetWithoutName_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception {
mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID) mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID)
.param(CommonAttribute.PET_TYPE, "hamster") .param(CommonAttribute.PET_TYPE, "hamster").param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12"))
.param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12")) .andExpect(model().attributeHasNoErrors(CommonAttribute.OWNER))
.andExpect(model().attributeHasNoErrors(CommonAttribute.OWNER)) .andExpect(model().attributeHasErrors(CommonAttribute.PET))
.andExpect(model().attributeHasErrors(CommonAttribute.PET)) .andExpect(model().attributeHasFieldErrors(CommonAttribute.PET, CommonAttribute.PET_NAME))
.andExpect(model().attributeHasFieldErrors(CommonAttribute.PET, CommonAttribute.PET_NAME)) .andExpect(model().attributeHasFieldErrorCode(CommonAttribute.PET, CommonAttribute.PET_NAME,
.andExpect(model().attributeHasFieldErrorCode(CommonAttribute.PET, CommonAttribute.PET_NAME, CommonError.REQUIRED_ARGS)) CommonError.REQUIRED_ARGS))
.andExpect(status().isOk()) .andExpect(status().isOk()).andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE));
.andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE));
} }
@Test @Test
@ -123,28 +121,26 @@ class PetControllerTest {
@DisplayName("Verify that return to Pet creation form when pet has no type") @DisplayName("Verify that return to Pet creation form when pet has no type")
void givenNewPetWithoutType_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception { void givenNewPetWithoutType_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception {
mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID) mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID)
.param(CommonAttribute.PET_NAME, "Betty") .param(CommonAttribute.PET_NAME, "Betty").param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12"))
.param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12")) .andExpect(model().attributeHasNoErrors(CommonAttribute.OWNER))
.andExpect(model().attributeHasNoErrors(CommonAttribute.OWNER)) .andExpect(model().attributeHasErrors(CommonAttribute.PET))
.andExpect(model().attributeHasErrors(CommonAttribute.PET)) .andExpect(model().attributeHasFieldErrors(CommonAttribute.PET, CommonAttribute.PET_TYPE))
.andExpect(model().attributeHasFieldErrors(CommonAttribute.PET, CommonAttribute.PET_TYPE)) .andExpect(model().attributeHasFieldErrorCode(CommonAttribute.PET, CommonAttribute.PET_TYPE,
.andExpect(model().attributeHasFieldErrorCode(CommonAttribute.PET, CommonAttribute.PET_TYPE, CommonError.REQUIRED_ARGS)) CommonError.REQUIRED_ARGS))
.andExpect(status().isOk()) .andExpect(status().isOk()).andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE));
.andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE));
} }
@Test @Test
@Tag("processCreationForm") @Tag("processCreationForm")
@DisplayName("Verify that return to Pet creation form when pet has wrong Owner ID") @DisplayName("Verify that return to Pet creation form when pet has wrong Owner ID")
void givenNewPetWithWrongOwner_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception { void givenNewPetWithWrongOwner_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception {
mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, 22) mockMvc.perform(
.param(CommonAttribute.PET_NAME, "Betty") post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, 22).param(CommonAttribute.PET_NAME, "Betty")
.param(CommonAttribute.PET_TYPE, "hamster") .param(CommonAttribute.PET_TYPE, "hamster").param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12"))
.param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12")) .andExpect(model().attributeHasErrors(CommonAttribute.PET))
.andExpect(model().attributeHasErrors(CommonAttribute.PET)) .andExpect(model().attributeHasFieldErrorCode(CommonAttribute.PET, CommonAttribute.OWNER,
.andExpect(model().attributeHasFieldErrorCode(CommonAttribute.PET, CommonAttribute.OWNER, CommonError.NOT_FOUND_ARGS)) CommonError.NOT_FOUND_ARGS))
.andExpect(status().isOk()) .andExpect(status().isOk()).andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE));
.andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE));
} }
@Test @Test
@ -153,14 +149,13 @@ class PetControllerTest {
void givenNewPetWithoutBirthDate_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception { void givenNewPetWithoutBirthDate_whenPostNewPet_thenSavePetAndRedirectToOwnerView() throws Exception {
mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID) mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID)
.param(CommonAttribute.PET_NAME, "Betty") .param(CommonAttribute.PET_NAME, "Betty").param(CommonAttribute.PET_TYPE, "hamster"))
.param(CommonAttribute.PET_TYPE, "hamster")) .andExpect(model().attributeHasNoErrors(CommonAttribute.OWNER))
.andExpect(model().attributeHasNoErrors(CommonAttribute.OWNER)) .andExpect(model().attributeHasErrors(CommonAttribute.PET))
.andExpect(model().attributeHasErrors(CommonAttribute.PET)) .andExpect(model().attributeHasFieldErrors(CommonAttribute.PET, CommonAttribute.PET_BIRTH_DATE))
.andExpect(model().attributeHasFieldErrors(CommonAttribute.PET, CommonAttribute.PET_BIRTH_DATE)) .andExpect(model().attributeHasFieldErrorCode(CommonAttribute.PET, CommonAttribute.PET_BIRTH_DATE,
.andExpect(model().attributeHasFieldErrorCode(CommonAttribute.PET, CommonAttribute.PET_BIRTH_DATE, CommonError.REQUIRED_ARGS)) CommonError.REQUIRED_ARGS))
.andExpect(status().isOk()) .andExpect(status().isOk()).andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE));
.andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE));
} }
@Test @Test

View file

@ -1,6 +1,5 @@
package org.springframework.samples.petclinic.controller; package org.springframework.samples.petclinic.controller;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -24,18 +23,21 @@ import org.springframework.test.web.servlet.MvcResult;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Objects;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
/** /**
* Test class for the {@link VetController}
*
* @author Paul-Emmanuel DOS SANTOS FACAO * @author Paul-Emmanuel DOS SANTOS FACAO
*/ */
@Slf4j @Slf4j
@SpringBootTest @SpringBootTest
@AutoConfigureMockMvc @AutoConfigureMockMvc
public class VetControllerIntegrationTest { class VetControllerIntegrationTest {
@Autowired @Autowired
private MockMvc mockMvc; private MockMvc mockMvc;
@ -54,19 +56,16 @@ public class VetControllerIntegrationTest {
expected = new VetsDTO(vetService.entitiesToDTOS(new ArrayList<>(vets))); expected = new VetsDTO(vetService.entitiesToDTOS(new ArrayList<>(vets)));
} }
@Test @Test
@Tag("showVetList") @Tag("showVetList")
@DisplayName("When asking vets get String containing Vets") @DisplayName("When asking vets get String containing Vets")
void whenGetVets_thenReturnStringOfVets() throws Exception { void whenGetVets_thenReturnStringOfVets() throws Exception {
final MvcResult result = mockMvc.perform(get(CommonEndPoint.VETS_HTML)) final MvcResult result = mockMvc.perform(get(CommonEndPoint.VETS_HTML)).andExpect(status().is2xxSuccessful())
.andExpect(status().is2xxSuccessful()) .andExpect(model().attributeExists(CommonAttribute.VETS))
.andExpect(model().attributeExists(CommonAttribute.VETS)) .andExpect(view().name(CommonView.VET_VETS_LIST)).andReturn();
.andExpect(view().name(CommonView.VET_VETS_LIST))
.andReturn();
VetsDTO found = (VetsDTO) result.getModelAndView().getModel().get(CommonAttribute.VETS); VetsDTO found = (VetsDTO) Objects.requireNonNull(result.getModelAndView()).getModel().get(CommonAttribute.VETS);
assertThat(found).isEqualToComparingFieldByField(expected); assertThat(found).isEqualToComparingFieldByField(expected);
} }
@ -78,9 +77,8 @@ public class VetControllerIntegrationTest {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
final MvcResult result = mockMvc.perform(get(CommonEndPoint.VETS)) final MvcResult result = mockMvc.perform(get(CommonEndPoint.VETS)).andExpect(status().is2xxSuccessful())
.andExpect(status().is2xxSuccessful()) .andReturn();
.andReturn();
String json = result.getResponse().getContentAsString(StandardCharsets.UTF_8); String json = result.getResponse().getContentAsString(StandardCharsets.UTF_8);

View file

@ -16,6 +16,7 @@
package org.springframework.samples.petclinic.controller; package org.springframework.samples.petclinic.controller;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given; 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.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
@ -24,11 +25,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.assertj.core.util.Lists; import org.assertj.core.util.Lists;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.*;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
@ -38,11 +38,16 @@ import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonView; import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.dto.SpecialtyDTO; import org.springframework.samples.petclinic.dto.SpecialtyDTO;
import org.springframework.samples.petclinic.dto.VetDTO; import org.springframework.samples.petclinic.dto.VetDTO;
import org.springframework.samples.petclinic.dto.VetsDTO;
import org.springframework.samples.petclinic.service.VetService; import org.springframework.samples.petclinic.service.VetService;
import org.springframework.samples.petclinic.model.Specialty;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.ResultActions;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
/** /**
* Test class for the {@link VetController} * Test class for the {@link VetController}
* *
@ -57,8 +62,10 @@ class VetControllerTest {
@MockBean @MockBean
private VetService vetService; private VetService vetService;
@BeforeEach static List<VetDTO> vetDTOS;
void beforeEach() {
@BeforeAll
static void beforeAll() {
VetDTO james = new VetDTO(); VetDTO james = new VetDTO();
james.setFirstName("James"); james.setFirstName("James");
james.setLastName("Carter"); james.setLastName("Carter");
@ -71,27 +78,43 @@ class VetControllerTest {
radiology.setId(1); radiology.setId(1);
radiology.setName("radiology"); radiology.setName("radiology");
helen.addSpecialty(radiology); helen.addSpecialty(radiology);
given(this.vetService.findAll()).willReturn(Lists.newArrayList(james, helen));
vetDTOS = Lists.newArrayList(james, helen);
}
@BeforeEach
void beforeEach() {
given(this.vetService.findAll()).willReturn(vetDTOS);
} }
@Test @Test
@Tag("showVetList") @Tag("showVetList")
@DisplayName("When asking vets get String containing Vets") @DisplayName("When asking vets get String containing Vets")
void whenGetVets_thenReturnStringOfVets() throws Exception { void whenGetVets_thenReturnStringOfVets() throws Exception {
mockMvc.perform(get(CommonEndPoint.VETS_HTML)).andExpect(status().isOk()) final MvcResult result = mockMvc.perform(get(CommonEndPoint.VETS_HTML)).andExpect(status().is2xxSuccessful())
.andExpect(model().attributeExists(CommonAttribute.VETS)) .andExpect(model().attributeExists(CommonAttribute.VETS))
.andExpect(view().name(CommonView.VET_VETS_LIST)); .andExpect(view().name(CommonView.VET_VETS_LIST)).andReturn();
VetsDTO found = (VetsDTO) Objects.requireNonNull(result.getModelAndView()).getModel().get(CommonAttribute.VETS);
assertThat(found.getVetList()).isEqualTo(vetDTOS);
} }
@Test @Test
@Tag("showResourcesVetList") @Tag("showResourcesVetList")
@DisplayName("When asking vets get Vets DTO object containing Vets") @DisplayName("When asking vets get Vets DTO object containing Vets")
void whenGetVets_thenReturnVetsDTO() throws Exception { void whenGetVets_thenReturnVetsDTO() throws Exception {
ResultActions actions = mockMvc.perform(get(CommonEndPoint.VETS).accept(MediaType.APPLICATION_JSON)) ObjectMapper mapper = new ObjectMapper();
.andExpect(status().isOk()); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
actions.andExpect(content().contentType(MediaType.APPLICATION_JSON)) final MvcResult result = mockMvc.perform(get(CommonEndPoint.VETS).accept(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.vetList[0].id").value(1)); .andExpect(status().is2xxSuccessful()).andReturn();
String json = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
VetsDTO found = mapper.readValue(json, VetsDTO.class);
assertThat(found.getVetList()).isEqualTo(vetDTOS);
} }
} }

View file

@ -0,0 +1,106 @@
package org.springframework.samples.petclinic.controller;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.dto.PetDTO;
import org.springframework.samples.petclinic.dto.VisitDTO;
import org.springframework.samples.petclinic.model.Visit;
import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.samples.petclinic.service.PetService;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
/**
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@Slf4j
@SpringBootTest
@AutoConfigureMockMvc
class VisitControllerIntegrationTest {
// An existing Pet ID in database
private final static Integer PET_ID = 5;
@Autowired
private MockMvc mockMvc;
@Autowired
private VisitRepository visitRepository;
@Autowired
private PetService petService;
private PetDTO petDTO;
private Visit visit;
private VisitDTO visitDTO;
@BeforeEach
void beforeEach() {
petDTO = petService.findById(PET_ID);
visit = new Visit();
visit.setPetId(PET_ID);
visit.setDate(LocalDate.now());
visit.setDescription("Visit Description");
visitDTO = new VisitDTO();
visitDTO.setPetId(PET_ID);
visitDTO.setDate(LocalDate.now());
visitDTO.setDescription("Visit Description");
}
@Test
@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))
.andReturn();
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());
expected.setPetId(PET_ID);
assertThat(found.getVisits()).contains(expected);
}
@Test
@Tag("processNewVisitForm")
@DisplayName("Verify that save Visit")
void givenVisitAndOwnerIDAndPetId_whenSaveVisit_thenSaveVisit() throws Exception {
mockMvc.perform(post(CommonEndPoint.VISITS_EDIT, petDTO.getOwner().getId(), PET_ID)
.flashAttr(CommonAttribute.VISIT, visitDTO)).andExpect(status().is3xxRedirection())
.andExpect(view().name(CommonView.OWNER_OWNERS_ID_R)).andReturn();
List<Visit> found = visitRepository.findByPetId(PET_ID);
assertThat(found).contains(visit);
}
}

View file

@ -16,16 +16,19 @@
package org.springframework.samples.petclinic.controller; package org.springframework.samples.petclinic.controller;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.*;
import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
@ -33,19 +36,40 @@ import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint; import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonView; import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.dto.PetDTO; 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.Visit;
import org.springframework.samples.petclinic.service.PetService; import org.springframework.samples.petclinic.service.PetService;
import org.springframework.samples.petclinic.service.VisitService; import org.springframework.samples.petclinic.service.VisitService;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import java.time.LocalDate;
import java.util.Objects;
/** /**
* Test class for {@link VisitController} * Test class for {@link VisitController}
* *
* @author Colin But * @author Colin But
* @author Paul-Emmanuel DOS SANTOS FACAO
*/ */
@WebMvcTest(VisitController.class) @WebMvcTest(VisitController.class)
@ExtendWith(MockitoExtension.class)
class VisitControllerTest { class VisitControllerTest {
private static final int TEST_PET_ID = 1; private final static Integer OWNER_ID = 5;
private final static Integer PET_ID = 14;
private final static Integer PET_TYPE_ID = 6;
private final static String PET_TYPE_NAME = "dragon";
private final static String PET_NAME = "bowser";
private final static String PET_BIRTH_DATE = "2020-07-11";
private final static String VISIT_DESCRIPTION = "Visit Description";
@Autowired @Autowired
private MockMvc mockMvc; private MockMvc mockMvc;
@ -56,31 +80,88 @@ class VisitControllerTest {
@MockBean @MockBean
private PetService petService; private PetService petService;
static private PetDTO petDTO;
private Visit visit;
private VisitDTO visitDTO;
@BeforeAll
static void beforeAll() {
PetTypeDTO petTypeDTO = new PetTypeDTO();
petTypeDTO.setName(PET_TYPE_NAME);
petTypeDTO.setId(PET_TYPE_ID);
petDTO = new PetDTO();
petDTO.setId(PET_ID);
petDTO.setName(PET_NAME);
petDTO.setType(petTypeDTO);
petDTO.setBirthDate(LocalDate.parse(PET_BIRTH_DATE));
}
@BeforeEach @BeforeEach
void init() { void beforeEach() {
given(this.petService.findById(TEST_PET_ID)).willReturn(new PetDTO()); visitDTO = new VisitDTO();
visitDTO.setPetId(PET_ID);
visitDTO.setDate(LocalDate.now());
visitDTO.setDescription(VISIT_DESCRIPTION);
} }
@Test @Test
@Tag("initNewVisitForm") @Tag("initNewVisitForm")
@DisplayName("Verify that return form for new Visit with right Pet")
void testInitNewVisitForm() throws Exception { void testInitNewVisitForm() throws Exception {
mockMvc.perform(get(CommonEndPoint.VISITS_NEW, TEST_PET_ID)).andExpect(status().isOk()) given(this.petService.findById(PET_ID)).willReturn(petDTO);
final MvcResult result = mockMvc.perform(get(CommonEndPoint.VISITS_NEW, PET_ID))
.andExpect(status().is2xxSuccessful()).andExpect(view().name(CommonView.VISIT_CREATE_OR_UPDATE))
.andReturn();
PetDTO found = (PetDTO) Objects.requireNonNull(result.getModelAndView()).getModel().get(CommonAttribute.PET);
assertThat(found).isEqualToIgnoringGivenFields(petDTO, CommonAttribute.VISITS);
VisitDTO expected = new VisitDTO();
expected.setDate(LocalDate.now());
expected.setPetId(PET_ID);
assertThat(found.getVisits()).contains(expected);
}
@Test
@Tag("processNewVisitForm")
@DisplayName("Verify that save Visit")
void givenVisitAndOwnerIDAndPetId_whenSaveVisit_thenSaveVisit() throws Exception {
ArgumentCaptor<VisitDTO> captor = ArgumentCaptor.forClass(VisitDTO.class);
mockMvc.perform(post(CommonEndPoint.VISITS_EDIT, OWNER_ID, PET_ID).flashAttr(CommonAttribute.VISIT, visitDTO))
.andExpect(status().is3xxRedirection()).andExpect(view().name(CommonView.OWNER_OWNERS_ID_R))
.andReturn();
verify(visitService, times(1)).save(captor.capture());
assertThat(captor.getValue()).isEqualTo(visitDTO);
}
@Test
@Tag("processNewVisitForm")
@DisplayName("Verify that return to update Visit view if Visit has no date")
void givenVisitAndOwnerIDAndPetIdAndVisitWithoutDate_whenSaveVisit_thenReturnToCreationView() throws Exception {
visitDTO.setDate(null);
mockMvc.perform(post(CommonEndPoint.VISITS_EDIT, OWNER_ID, PET_ID).flashAttr(CommonAttribute.PET, petDTO)
.flashAttr(CommonAttribute.VISIT, visitDTO)).andExpect(status().is2xxSuccessful())
.andExpect(view().name(CommonView.VISIT_CREATE_OR_UPDATE)); .andExpect(view().name(CommonView.VISIT_CREATE_OR_UPDATE));
} }
@Test @Test
@Tag("processNewVisitForm") @Tag("processNewVisitForm")
void testProcessNewVisitFormSuccess() throws Exception { @DisplayName("Verify that return to update Visit view if Visit has no description")
mockMvc.perform(post(CommonEndPoint.VISITS_NEW, TEST_PET_ID).param(CommonAttribute.NAME, "George") void givenVisitAndOwnerIDAndPetIdAndVisitWithoutDescription_whenSaveVisit_thenReturnToCreationView()
.param(CommonAttribute.DESCRIPTION, "Visit Description")).andExpect(status().is3xxRedirection()) throws Exception {
.andExpect(view().name(CommonView.OWNER_OWNERS_ID_R)); visitDTO.setDescription("");
}
@Test mockMvc.perform(post(CommonEndPoint.VISITS_EDIT, OWNER_ID, PET_ID).flashAttr(CommonAttribute.PET, petDTO)
@Tag("processNewVisitForm") .flashAttr(CommonAttribute.VISIT, visitDTO)).andExpect(status().is2xxSuccessful())
void testProcessNewVisitFormHasErrors() throws Exception {
mockMvc.perform(post(CommonEndPoint.VISITS_NEW, TEST_PET_ID).param(CommonAttribute.NAME, "George"))
.andExpect(model().attributeHasErrors(CommonAttribute.VISIT)).andExpect(status().isOk())
.andExpect(view().name(CommonView.VISIT_CREATE_OR_UPDATE)); .andExpect(view().name(CommonView.VISIT_CREATE_OR_UPDATE));
} }