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_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() {
throw new IllegalStateException("Utility class");
}

View file

@ -47,7 +47,6 @@ class PetController {
private final PetService petService;
@Autowired
PetController(OwnerService ownerService, PetService petService, PetTypeService petTypeService) {
this.ownerService = ownerService;
@ -87,14 +86,14 @@ class PetController {
@ModelAttribute(CommonAttribute.PET) @Valid PetDTO pet, BindingResult result, ModelMap model) {
if (owner == null) {
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) {
result.rejectValue(CommonAttribute.NAME, CommonError.DUPLICATE_ARGS, CommonError.DUPLICATE_MESSAGE);
}
owner.addPet(pet);
}
if (result.hasErrors()) {
model.put(CommonAttribute.PET, pet);
return CommonView.PET_CREATE_OR_UPDATE;

View file

@ -52,7 +52,7 @@ class VetController {
return CommonView.VET_VETS_LIST;
}
@GetMapping({ CommonEndPoint.VETS })
@GetMapping(CommonEndPoint.VETS)
public @ResponseBody VetsDTO showResourcesVetList() {
// Here we are returning an object of type 'Vets' rather than a collection of Vet
// 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.service.PetService;
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.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
@ -77,6 +79,11 @@ class VisitController {
return visit;
}
@InitBinder("visit")
public void initVisitBinder(WebDataBinder dataBinder) {
dataBinder.setValidator(new VisitDTOValidator());
}
// Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called
@GetMapping(CommonEndPoint.VISITS_NEW)
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 javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
/**
@ -26,12 +27,14 @@ 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;
/**
@ -76,7 +79,8 @@ public class VisitDTO extends BaseDTO {
if (!getDate().equals(visitDTO.getDate()))
return false;
if (!getDescription().equals(visitDTO.getDescription()))
if (getDescription() != null ? !getDescription().equals(visitDTO.getDescription())
: visitDTO.getDescription() != null)
return false;
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 {
private static final int TEST_OWNER_ID = 5;
private static final int TEST_PET_ID = 6;
@Autowired
@ -75,7 +76,8 @@ class PetControllerIntegrationTest {
final MvcResult result = mockMvc
.perform(get(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID)
.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);
@ -104,9 +106,10 @@ class PetControllerIntegrationTest {
void givenPetId_whenGetUpdatePet_thenReturnUpdateViewWithPet() throws Exception {
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))
.andExpect(status().isOk()).andExpect(model().attributeExists(CommonAttribute.PET))
.andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE)).andReturn();
final MvcResult result = mockMvc
.perform(get(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_ID_EDIT, TEST_OWNER_ID, TEST_PET_ID))
.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);
@ -122,13 +125,14 @@ class PetControllerIntegrationTest {
petExpected.setName("Nabucho");
petExpected.setBirthDate(LocalDate.now());
final MvcResult result = mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_ID_EDIT, ownerExpected.getId(), petExpected.getId())
.flashAttr(CommonAttribute.OWNER, ownerExpected).flashAttr(CommonAttribute.PET, petExpected))
.andExpect(view().name(CommonView.OWNER_OWNERS_ID_R))
.andReturn();
final MvcResult result = mockMvc.perform(
post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_ID_EDIT, ownerExpected.getId(), petExpected.getId())
.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));
assertThat(petFound).isEqualTo(petExpected);
}
}

View file

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

View file

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

View file

@ -16,6 +16,7 @@
package org.springframework.samples.petclinic.controller;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
@ -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.view;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.assertj.core.util.Lists;
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.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
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.dto.SpecialtyDTO;
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.model.Specialty;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
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}
*
@ -57,8 +62,10 @@ class VetControllerTest {
@MockBean
private VetService vetService;
@BeforeEach
void beforeEach() {
static List<VetDTO> vetDTOS;
@BeforeAll
static void beforeAll() {
VetDTO james = new VetDTO();
james.setFirstName("James");
james.setLastName("Carter");
@ -71,27 +78,43 @@ class VetControllerTest {
radiology.setId(1);
radiology.setName("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
@Tag("showVetList")
@DisplayName("When asking vets get String containing Vets")
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(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
@Tag("showResourcesVetList")
@DisplayName("When asking vets get Vets DTO object containing Vets")
void whenGetVets_thenReturnVetsDTO() throws Exception {
ResultActions actions = mockMvc.perform(get(CommonEndPoint.VETS).accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
actions.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.vetList[0].id").value(1));
final MvcResult result = mockMvc.perform(get(CommonEndPoint.VETS).accept(MediaType.APPLICATION_JSON))
.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;
import static org.assertj.core.api.Assertions.assertThat;
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.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
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.CommonView;
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.VisitService;
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}
*
* @author Colin But
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@WebMvcTest(VisitController.class)
@ExtendWith(MockitoExtension.class)
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
private MockMvc mockMvc;
@ -56,31 +80,88 @@ class VisitControllerTest {
@MockBean
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
void init() {
given(this.petService.findById(TEST_PET_ID)).willReturn(new PetDTO());
void beforeEach() {
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 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));
}
@Test
@Tag("processNewVisitForm")
void testProcessNewVisitFormSuccess() throws Exception {
mockMvc.perform(post(CommonEndPoint.VISITS_NEW, TEST_PET_ID).param(CommonAttribute.NAME, "George")
.param(CommonAttribute.DESCRIPTION, "Visit Description")).andExpect(status().is3xxRedirection())
.andExpect(view().name(CommonView.OWNER_OWNERS_ID_R));
}
@DisplayName("Verify that return to update Visit view if Visit has no description")
void givenVisitAndOwnerIDAndPetIdAndVisitWithoutDescription_whenSaveVisit_thenReturnToCreationView()
throws Exception {
visitDTO.setDescription("");
@Test
@Tag("processNewVisitForm")
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())
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));
}