mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-07-19 05:55:51 +00:00
Save pet attributes and retrieve them feature completed.
This commit is contained in:
parent
e76ed81718
commit
8c8509b46e
17 changed files with 621 additions and 5 deletions
BIN
src.zip
BIN
src.zip
Binary file not shown.
|
@ -0,0 +1,67 @@
|
|||
package org.springframework.samples.petclinic.owner.controller;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.samples.petclinic.owner.dto.PetAttributesDTO;
|
||||
import org.springframework.samples.petclinic.owner.expection.PetNotFoundException;
|
||||
import org.springframework.samples.petclinic.owner.model.PetAttributes;
|
||||
import org.springframework.samples.petclinic.owner.repository.PetRepository;
|
||||
import org.springframework.samples.petclinic.owner.service.PetAttributesService;
|
||||
import org.springframework.samples.petclinic.owner.validation.PetIdExistsValidator;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/pets/{petId}/attributes")
|
||||
public class PetAttributesController {
|
||||
|
||||
private final PetAttributesService petAttributesService;
|
||||
|
||||
private PetIdExistsValidator petIdExistsValidator;
|
||||
|
||||
private PetRepository petRepository;
|
||||
|
||||
public PetAttributesController(PetIdExistsValidator petIdExistsValidator, PetAttributesService petAttributesService,
|
||||
PetRepository petRepository) {
|
||||
this.petIdExistsValidator = petIdExistsValidator;
|
||||
this.petAttributesService = petAttributesService;
|
||||
this.petRepository = petRepository;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<?> getPetAttributes(@PathVariable("petId") int petId) {
|
||||
if (!petRepository.existsById(petId)) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Pet not found");
|
||||
}
|
||||
|
||||
Optional<PetAttributes> optionalAttributes = petAttributesService.findByPetId(petId);
|
||||
|
||||
return optionalAttributes.<ResponseEntity<?>>map(ResponseEntity::ok)
|
||||
.orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND).body("Attributes not found"));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity savePetAttributes(@PathVariable int petId, @Valid @RequestBody PetAttributesDTO dto,
|
||||
BindingResult bindingResult) {
|
||||
// Validate petId exists
|
||||
petIdExistsValidator.validate(petId, bindingResult);
|
||||
|
||||
if (bindingResult.hasErrors()) {
|
||||
return ResponseEntity.badRequest().body(bindingResult.getAllErrors());
|
||||
}
|
||||
|
||||
dto.setPetId(petId);
|
||||
|
||||
try {
|
||||
petAttributesService.savePetAttributes(dto);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body("Pet attributes saved");
|
||||
} catch (PetNotFoundException e) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -72,7 +72,7 @@ public class PetController {
|
|||
|
||||
@ModelAttribute("pet")
|
||||
public Pet findPet(@PathVariable("ownerId") int ownerId,
|
||||
@PathVariable(name = "petId", required = false) Integer petId) {
|
||||
@PathVariable(name = "petId", required = false) Integer petId) {
|
||||
|
||||
if (petId == null) {
|
||||
return new Pet();
|
||||
|
|
|
@ -65,7 +65,7 @@ public class VisitController {
|
|||
*/
|
||||
@ModelAttribute("visit")
|
||||
public Visit loadPetWithVisit(@PathVariable("ownerId") int ownerId, @PathVariable("petId") int petId,
|
||||
Map<String, Object> model) {
|
||||
Map<String, Object> model) {
|
||||
Optional<Owner> optionalOwner = owners.findById(ownerId);
|
||||
Owner owner = optionalOwner.orElseThrow(() -> new IllegalArgumentException(
|
||||
"Owner not found with id: " + ownerId + ". Please ensure the ID is correct "));
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package org.springframework.samples.petclinic.owner.dto;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class PetAttributesDTO {
|
||||
|
||||
@NotNull(message = "Pet ID is required")
|
||||
private int petId;
|
||||
|
||||
@NotBlank(message = "Temperament is required")
|
||||
@Size(max = 100, message = "Temperament must not exceed 100 characters")
|
||||
private String temperament;
|
||||
|
||||
@NotNull
|
||||
@DecimalMin(value = "0.1", inclusive = true, message = "Length must be at least 0.1 cm")
|
||||
@DecimalMax(value = "500.0", inclusive = true, message = "Length must be less than or equal to 500 cm")
|
||||
private BigDecimal lengthCm;
|
||||
|
||||
@NotNull
|
||||
@DecimalMin(value = "0.1", inclusive = true, message = "Weight must be at least 0.1 kg")
|
||||
@DecimalMax(value = "500.0", inclusive = true, message = "Weight must be less than or equal to 500 kg")
|
||||
private BigDecimal weightKg;
|
||||
|
||||
// Getters and setters
|
||||
|
||||
public int getPetId() {
|
||||
return petId;
|
||||
}
|
||||
|
||||
public void setPetId(int petId) {
|
||||
this.petId = petId;
|
||||
}
|
||||
|
||||
public String getTemperament() {
|
||||
return temperament;
|
||||
}
|
||||
|
||||
public void setTemperament(String temperament) {
|
||||
this.temperament = temperament;
|
||||
}
|
||||
|
||||
public BigDecimal getLengthCm() {
|
||||
return lengthCm;
|
||||
}
|
||||
|
||||
public void setLengthCm(BigDecimal lengthCm) {
|
||||
this.lengthCm = lengthCm;
|
||||
}
|
||||
|
||||
public BigDecimal getWeightKg() {
|
||||
return weightKg;
|
||||
}
|
||||
|
||||
public void setWeightKg(BigDecimal weightKg) {
|
||||
this.weightKg = weightKg;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package org.springframework.samples.petclinic.owner.expection;
|
||||
|
||||
public class PetNotFoundException extends RuntimeException {
|
||||
|
||||
public PetNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package org.springframework.samples.petclinic.owner.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Entity
|
||||
@Table(name = "pet_attributes")
|
||||
public class PetAttributes {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Integer id;
|
||||
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "pet_id", nullable = false)
|
||||
@JsonIgnore
|
||||
private Pet pet;
|
||||
|
||||
private String temperament;
|
||||
|
||||
@Column(name = "length_cm", precision = 5, scale = 2)
|
||||
private BigDecimal lengthCm;
|
||||
|
||||
@Column(name = "weight_kg", precision = 5, scale = 2)
|
||||
private BigDecimal weightKg;
|
||||
|
||||
@Column(name = "additional_attributes", columnDefinition = "json")
|
||||
private String additionalAttributes;
|
||||
|
||||
// --- Getters and Setters ---
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Pet getPet() {
|
||||
return pet;
|
||||
}
|
||||
|
||||
public void setPet(Pet pet) {
|
||||
this.pet = pet;
|
||||
}
|
||||
|
||||
public String getTemperament() {
|
||||
return temperament;
|
||||
}
|
||||
|
||||
public void setTemperament(String temperament) {
|
||||
this.temperament = temperament;
|
||||
}
|
||||
|
||||
public BigDecimal getLengthCm() {
|
||||
return lengthCm;
|
||||
}
|
||||
|
||||
public void setLengthCm(BigDecimal lengthCm) {
|
||||
this.lengthCm = lengthCm;
|
||||
}
|
||||
|
||||
public BigDecimal getWeightKg() {
|
||||
return weightKg;
|
||||
}
|
||||
|
||||
public void setWeightKg(BigDecimal weightKg) {
|
||||
this.weightKg = weightKg;
|
||||
}
|
||||
|
||||
public String getAdditionalAttributes() {
|
||||
return additionalAttributes;
|
||||
}
|
||||
|
||||
public void setAdditionalAttributes(String additionalAttributes) {
|
||||
this.additionalAttributes = additionalAttributes;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package org.springframework.samples.petclinic.owner.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.samples.petclinic.owner.model.PetAttributes;
|
||||
|
||||
/**
|
||||
* Repository class for <code>PetAttributes</code> domain objects. Provides CRUD
|
||||
* operations and custom query methods related to a pet's attributes.
|
||||
*
|
||||
* @see org.springframework.samples.petclinic.owner.model.PetAttributes
|
||||
*/
|
||||
public interface PetAttributesRepository extends JpaRepository<PetAttributes, Integer> {
|
||||
|
||||
/**
|
||||
* Find pet attributes by pet ID.
|
||||
*
|
||||
* @param petId the ID of the pet
|
||||
* @return an Optional containing the PetAttributes if found
|
||||
*/
|
||||
Optional<PetAttributes> findByPetId(Integer petId);
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package org.springframework.samples.petclinic.owner.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.samples.petclinic.owner.model.Pet;
|
||||
|
||||
public interface PetRepository extends JpaRepository<Pet, Integer> {
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package org.springframework.samples.petclinic.owner.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.samples.petclinic.owner.dto.PetAttributesDTO;
|
||||
import org.springframework.samples.petclinic.owner.expection.PetNotFoundException;
|
||||
import org.springframework.samples.petclinic.owner.model.Pet;
|
||||
import org.springframework.samples.petclinic.owner.model.PetAttributes;
|
||||
import org.springframework.samples.petclinic.owner.repository.PetAttributesRepository;
|
||||
import org.springframework.samples.petclinic.owner.repository.PetRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class PetAttributesService {
|
||||
|
||||
private final PetAttributesRepository petAttributesRepository;
|
||||
|
||||
private final PetRepository petRepository;
|
||||
|
||||
@Autowired
|
||||
public PetAttributesService(PetAttributesRepository petAttributesRepository, PetRepository petRepository) {
|
||||
this.petAttributesRepository = petAttributesRepository;
|
||||
this.petRepository = petRepository;
|
||||
}
|
||||
|
||||
public Optional<PetAttributes> findByPetId(Integer petId) {
|
||||
return petAttributesRepository.findByPetId(petId);
|
||||
}
|
||||
|
||||
public void savePetAttributes(PetAttributesDTO dto) {
|
||||
Optional<Pet> pet = petRepository.findById(dto.getPetId());
|
||||
|
||||
if (pet.isEmpty()) {
|
||||
throw new PetNotFoundException("Pet not found");
|
||||
}
|
||||
|
||||
PetAttributes attributes = petAttributesRepository.findByPetId(dto.getPetId()).orElse(new PetAttributes());
|
||||
|
||||
attributes.setPet(pet.get());
|
||||
attributes.setTemperament(dto.getTemperament());
|
||||
attributes.setLengthCm(dto.getLengthCm());
|
||||
attributes.setWeightKg(dto.getWeightKg());
|
||||
petAttributesRepository.save(attributes);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package org.springframework.samples.petclinic.owner.validation;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.samples.petclinic.owner.repository.PetRepository;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.Validator;
|
||||
|
||||
@Component
|
||||
public class PetIdExistsValidator implements Validator {
|
||||
|
||||
private final PetRepository petRepository;
|
||||
|
||||
@Autowired
|
||||
public PetIdExistsValidator(PetRepository petRepository) {
|
||||
this.petRepository = petRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> clazz) {
|
||||
// This validator supports Integer class, for validating petId field
|
||||
return Integer.class.equals(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(Object target, Errors errors) {
|
||||
if (target == null) {
|
||||
errors.reject("petId.null", "Pet ID is required");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(target instanceof Integer)) {
|
||||
errors.reject("petId.type", "Pet ID must be an integer");
|
||||
return;
|
||||
}
|
||||
|
||||
Integer petId = (Integer) target;
|
||||
|
||||
if (petId <= 0) {
|
||||
errors.rejectValue("", "petId.positive", "Pet ID must be a positive number");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!petRepository.existsById(petId)) {
|
||||
errors.rejectValue("", "petId.notFound", "Pet with ID " + petId + " does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -8,7 +8,7 @@ spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
|||
database=mysql
|
||||
spring.datasource.url=${MYSQL_URL:jdbc:mysql://localhost/petclinic}
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=testA@123
|
||||
spring.datasource.password=your-password
|
||||
# SQL is written to be idempotent so this is safe
|
||||
spring.sql.init.mode=always
|
||||
|
||||
|
|
|
@ -53,3 +53,13 @@ CREATE TABLE IF NOT EXISTS visits (
|
|||
description VARCHAR(255),
|
||||
FOREIGN KEY (pet_id) REFERENCES pets(id)
|
||||
) engine=InnoDB;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS pet_attributes (
|
||||
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
pet_id INT UNSIGNED NOT NULL,
|
||||
temperament VARCHAR(100),
|
||||
length_cm DECIMAL(5,2),
|
||||
weight_kg DECIMAL(5,2),
|
||||
additional_attributes JSON,
|
||||
FOREIGN KEY (pet_id) REFERENCES pets(id)
|
||||
);
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
package org.springframework.samples.petclinic.owner;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.samples.petclinic.owner.controller.PetAttributesController;
|
||||
import org.springframework.samples.petclinic.owner.dto.PetAttributesDTO;
|
||||
import org.springframework.samples.petclinic.owner.expection.PetNotFoundException;
|
||||
import org.springframework.samples.petclinic.owner.model.PetAttributes;
|
||||
import org.springframework.samples.petclinic.owner.repository.PetRepository;
|
||||
import org.springframework.samples.petclinic.owner.service.PetAttributesService;
|
||||
import org.springframework.samples.petclinic.owner.validation.PetIdExistsValidator;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.validation.BindingResult;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
@WebMvcTest(PetAttributesController.class)
|
||||
public class PetAttributesControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@MockBean
|
||||
private PetAttributesService petAttributesService;
|
||||
|
||||
@MockBean
|
||||
private PetIdExistsValidator petIdExistsValidator;
|
||||
|
||||
@MockBean
|
||||
private PetRepository petRepository;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Test
|
||||
void testGetPetAttributes_Found() throws Exception {
|
||||
int petId = 1;
|
||||
PetAttributes attributes = new PetAttributes();
|
||||
|
||||
Mockito.when(petRepository.existsById(petId)).thenReturn(true);
|
||||
Mockito.when(petAttributesService.findByPetId(petId)).thenReturn(Optional.of(attributes));
|
||||
|
||||
mockMvc.perform(get("/pets/{petId}/attributes", petId)).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPetAttributes_PetNotFound() throws Exception {
|
||||
int petId = 1;
|
||||
|
||||
Mockito.when(petRepository.existsById(petId)).thenReturn(false);
|
||||
|
||||
mockMvc.perform(get("/pets/{petId}/attributes", petId))
|
||||
.andExpect(status().isNotFound())
|
||||
.andExpect(content().string("Pet not found"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPetAttributes_AttributesNotFound() throws Exception {
|
||||
int petId = 1;
|
||||
|
||||
Mockito.when(petRepository.existsById(petId)).thenReturn(true);
|
||||
Mockito.when(petAttributesService.findByPetId(petId)).thenReturn(Optional.empty());
|
||||
|
||||
mockMvc.perform(get("/pets/{petId}/attributes", petId))
|
||||
.andExpect(status().isNotFound())
|
||||
.andExpect(content().string("Attributes not found"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSavePetAttributes_Success() throws Exception {
|
||||
int petId = 1;
|
||||
PetAttributesDTO dto = new PetAttributesDTO();
|
||||
dto.setTemperament("Calm");
|
||||
dto.setWeightKg(BigDecimal.valueOf(12.5));
|
||||
dto.setLengthCm(BigDecimal.valueOf(60.0));
|
||||
|
||||
Mockito.doNothing().when(petIdExistsValidator).validate(eq(petId), any(BindingResult.class));
|
||||
Mockito.doNothing().when(petAttributesService).savePetAttributes(any(PetAttributesDTO.class));
|
||||
|
||||
mockMvc
|
||||
.perform(post("/pets/{petId}/attributes", petId).contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(dto)))
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(content().string("Pet attributes saved"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSavePetAttributes_PetNotFoundException() throws Exception {
|
||||
int petId = 1;
|
||||
PetAttributesDTO dto = new PetAttributesDTO();
|
||||
dto.setTemperament("Aggressive");
|
||||
dto.setWeightKg(BigDecimal.valueOf(12.5));
|
||||
dto.setLengthCm(BigDecimal.valueOf(60.0));
|
||||
|
||||
Mockito.doNothing().when(petIdExistsValidator).validate(eq(petId), any(BindingResult.class));
|
||||
Mockito.doThrow(new PetNotFoundException("Pet not found"))
|
||||
.when(petAttributesService)
|
||||
.savePetAttributes(any(PetAttributesDTO.class));
|
||||
|
||||
mockMvc
|
||||
.perform(post("/pets/{petId}/attributes", petId).contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(dto)))
|
||||
.andExpect(status().isNotFound())
|
||||
.andExpect(content().string("Pet not found"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSavePetAttributes_ValidationErrors() throws Exception {
|
||||
int petId = 1;
|
||||
PetAttributesDTO dto = new PetAttributesDTO();
|
||||
dto.setTemperament("Friendly");
|
||||
dto.setWeightKg(BigDecimal.valueOf(10.0));
|
||||
dto.setLengthCm(BigDecimal.valueOf(50.0));
|
||||
|
||||
// Simulate petId validation failure
|
||||
Mockito.doAnswer(invocation -> {
|
||||
BindingResult result = invocation.getArgument(1);
|
||||
result.reject("petId", "Validation failed");
|
||||
return null;
|
||||
}).when(petIdExistsValidator).validate(eq(petId), any(BindingResult.class));
|
||||
|
||||
mockMvc
|
||||
.perform(post("/pets/{petId}/attributes", petId).contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(dto)))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$[0].code").value("petId"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package org.springframework.samples.petclinic.service;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.*;
|
||||
import org.springframework.samples.petclinic.owner.dto.PetAttributesDTO;
|
||||
import org.springframework.samples.petclinic.owner.expection.PetNotFoundException;
|
||||
import org.springframework.samples.petclinic.owner.model.Pet;
|
||||
import org.springframework.samples.petclinic.owner.model.PetAttributes;
|
||||
import org.springframework.samples.petclinic.owner.repository.PetAttributesRepository;
|
||||
import org.springframework.samples.petclinic.owner.repository.PetRepository;
|
||||
import org.springframework.samples.petclinic.owner.service.PetAttributesService;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class PetAttributesServiceTest {
|
||||
|
||||
@Mock
|
||||
private PetAttributesRepository petAttributesRepository;
|
||||
|
||||
@Mock
|
||||
private PetRepository petRepository;
|
||||
|
||||
@InjectMocks
|
||||
private PetAttributesService petAttributesService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindByPetId_ReturnsAttributes() {
|
||||
PetAttributes attributes = new PetAttributes();
|
||||
when(petAttributesRepository.findByPetId(1)).thenReturn(Optional.of(attributes));
|
||||
Optional<PetAttributes> result = petAttributesService.findByPetId(1);
|
||||
assertTrue(result.isPresent());
|
||||
assertEquals(attributes, result.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindByPetId_ReturnsEmpty() {
|
||||
when(petAttributesRepository.findByPetId(1)).thenReturn(Optional.empty());
|
||||
Optional<PetAttributes> result = petAttributesService.findByPetId(1);
|
||||
assertFalse(result.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSavePetAttributes_Success_NewRecord() {
|
||||
Pet pet = new Pet();
|
||||
pet.setId(1);
|
||||
|
||||
PetAttributesDTO dto = new PetAttributesDTO();
|
||||
dto.setPetId(1);
|
||||
dto.setTemperament("Calm");
|
||||
dto.setLengthCm(BigDecimal.valueOf(40.0));
|
||||
dto.setWeightKg(BigDecimal.valueOf(8.5));
|
||||
|
||||
when(petRepository.findById(1)).thenReturn(Optional.of(pet));
|
||||
when(petAttributesRepository.findByPetId(1)).thenReturn(Optional.empty());
|
||||
|
||||
petAttributesService.savePetAttributes(dto);
|
||||
|
||||
// Expect a new PetAttributes to be created and saved
|
||||
ArgumentCaptor<PetAttributes> captor = ArgumentCaptor.forClass(PetAttributes.class);
|
||||
verify(petAttributesRepository).save(captor.capture());
|
||||
|
||||
PetAttributes saved = captor.getValue();
|
||||
assertEquals("Calm", saved.getTemperament());
|
||||
assertEquals(BigDecimal.valueOf(40.0), saved.getLengthCm());
|
||||
assertEquals(BigDecimal.valueOf(8.5), saved.getWeightKg());
|
||||
assertEquals(pet, saved.getPet());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSavePetAttributes_Success_UpdateExisting() {
|
||||
Pet pet = new Pet();
|
||||
pet.setId(1);
|
||||
|
||||
PetAttributes existing = new PetAttributes();
|
||||
existing.setPet(pet);
|
||||
|
||||
PetAttributesDTO dto = new PetAttributesDTO();
|
||||
dto.setPetId(1);
|
||||
dto.setTemperament("Playful");
|
||||
dto.setLengthCm(BigDecimal.valueOf(45.0));
|
||||
dto.setWeightKg(BigDecimal.valueOf(9.0));
|
||||
|
||||
when(petRepository.findById(1)).thenReturn(Optional.of(pet));
|
||||
when(petAttributesRepository.findByPetId(1)).thenReturn(Optional.of(existing));
|
||||
|
||||
petAttributesService.savePetAttributes(dto);
|
||||
|
||||
verify(petAttributesRepository).save(existing);
|
||||
assertEquals("Playful", existing.getTemperament());
|
||||
assertEquals(BigDecimal.valueOf(45.0), existing.getLengthCm());
|
||||
assertEquals(BigDecimal.valueOf(9.0), existing.getWeightKg());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSavePetAttributes_PetNotFound_ThrowsException() {
|
||||
PetAttributesDTO dto = new PetAttributesDTO();
|
||||
dto.setPetId(1);
|
||||
|
||||
when(petRepository.findById(1)).thenReturn(Optional.empty());
|
||||
|
||||
PetNotFoundException ex = assertThrows(PetNotFoundException.class, () -> {
|
||||
petAttributesService.savePetAttributes(dto);
|
||||
});
|
||||
|
||||
assertEquals("Pet not found", ex.getMessage());
|
||||
verify(petAttributesRepository, never()).save(any());
|
||||
}
|
||||
|
||||
}
|
|
@ -41,7 +41,8 @@ import org.springframework.http.RequestEntity;
|
|||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
/**
|
||||
* Integration Test for {@link org.springframework.samples.petclinic.system.controller.CrashController}.
|
||||
* Integration Test for
|
||||
* {@link org.springframework.samples.petclinic.system.controller.CrashController}.
|
||||
*
|
||||
* @author Alex Lutz
|
||||
*/
|
||||
|
|
|
@ -22,7 +22,8 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|||
import org.springframework.samples.petclinic.system.controller.CrashController;
|
||||
|
||||
/**
|
||||
* Test class for {@link org.springframework.samples.petclinic.system.controller.CrashController}
|
||||
* Test class for
|
||||
* {@link org.springframework.samples.petclinic.system.controller.CrashController}
|
||||
*
|
||||
* @author Colin But
|
||||
* @author Alex Lutz
|
||||
|
|
Loading…
Reference in a new issue