# Org / Springframework / Samples / Petclinic / Service

## Overview

The `org.springframework.samples.petclinic.service` package contains integration tests that exercise the Petclinic repository/service layer against a real JPA persistence context. In practice, this package verifies that core clinic operations such as finding owners, saving pets, loading vets, and recording visits work correctly end to end.

This module exists to protect the behavior of the persistence-facing domain model. Rather than testing business logic in isolation, it validates that repository methods, entity mappings, and cascading relationships all behave as expected when Spring Data JPA is involved.

## Key Classes and Interfaces

### [`ClinicServiceTests`](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:70)

This is the main integration test class for the package. It is annotated with `@DataJpaTest`, so Spring boots only the JPA slice of the application and provides repository beans, transactional test execution, and an in-memory or configured test database.

The class injects three repositories:

- `OwnerRepository` for owner and pet persistence
- `PetTypeRepository` for pet type lookup
- `VetRepository` for vet lookup

It uses these repositories to verify the most important persistence use cases in Petclinic.

Key methods:

- [`shouldFindOwnersByLastName()`](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:87)
  - Calls `owners.findByLastNameStartingWith("Davis", pageable)` and asserts that two owners are returned.
  - Calls the same query with a misspelled prefix and asserts that no results are returned.
  - This checks the repository’s prefix-search behavior and pagination wiring.

- [`shouldFindSingleOwnerWithPet()`](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:96)
  - Loads owner `1` by id and verifies the owner exists.
  - Asserts the owner’s last name begins with `Franklin`, that exactly one pet is loaded, and that the pet has a non-null type named `cat`.
  - This confirms that the owner-pet-type object graph is populated correctly.

- [`shouldInsertOwner()`](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:107)
  - Counts owners whose last name starts with `Schultz`.
  - Creates a new `Owner`, sets its basic contact fields, and saves it through `OwnerRepository`.
  - Verifies that the generated id is assigned and that the count for the prefix increases by one.
  - Because the test is transactional, the insert is rolled back after the test.

- [`shouldUpdateOwner()`](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:126)
  - Loads owner `1`, changes the last name, saves the entity, then reloads it from the database.
  - Confirms that the updated last name was persisted.
  - This is an important check that the repository performs merge/update correctly.

- [`shouldFindAllPetTypes()`](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:145)
  - Reads all pet types via `PetTypeRepository`.
  - Uses `EntityUtils.getById(...)` to find the records with ids `1` and `4` and verifies their names are `cat` and `snake`.
  - This validates the reference data used when assigning a pet’s type.

- [`shouldInsertPetIntoDatabaseAndGenerateId()`](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:155)
  - Loads owner `6`, records the current number of pets, creates a new `Pet`, and assigns it a type from the repository.
  - Adds the pet to the owner, saves the owner, reloads the owner, and verifies the pet count increased.
  - Finally checks that the new pet received a generated id.
  - This test confirms the owner-pet relationship and cascading persistence behavior.

- [`shouldUpdatePetName()`](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:183)
  - Loads owner `6`, retrieves pet `7`, mutates the pet name, and saves the owner.
  - Reloads the owner and verifies the pet name change persisted.
  - This checks that changes to nested entities are tracked and stored correctly.

- [`shouldFindVets()`](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:204)
  - Fetches all vets from `VetRepository`.
  - Uses `EntityUtils` to locate vet `3` and verifies the last name and two specialties (`dentistry` and `surgery`).
  - This tests the vet reference data and specialty mapping.

- [`shouldAddNewVisitForPet()`](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:215)
  - Loads owner `6`, retrieves pet `7`, and records the current visit count.
  - Creates a new `Visit`, sets a description, attaches it via `owner6.addVisit(pet7.getId(), visit)`, and saves the owner.
  - Asserts that the pet now has one more visit and that the visit ids were generated.
  - This verifies the visit workflow and persistence of child entities.

- [`shouldFindVisitsByPetId()`](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:235)
  - Loads owner `6`, retrieves pet `7`, and inspects that pet’s visit collection.
  - Confirms there are two visits and that the first visit has a non-null date.
  - This validates that visit history is available through the pet association.

### [`EntityUtils`](src/test/java/org/springframework/samples/petclinic/service/EntityUtils.java:33)

`EntityUtils` is a small test utility used to search collections of entities by id. It is separate from `BaseEntity` because it throws `ObjectRetrievalFailureException`, which keeps the failure mode consistent with ORM-style entity lookup.

Key method:

- [`getById(Collection<T> entities, Class<T> entityClass, int entityId)`](src/test/java/org/springframework/samples/petclinic/service/EntityUtils.java:43)
  - Iterates over a collection of entities and returns the one whose id matches `entityId`.
  - Requires the entity to be an instance of `entityClass` and to have a non-null id.
  - Throws `ObjectRetrievalFailureException` if no matching entity is found.
  - This is useful in tests because it gives a concise way to assert against a specific record in an unordered collection.

## How It Works

The tests follow a consistent pattern:

1. Load existing reference data through a repository.
2. Mutate or inspect the entity graph.
3. Save the root entity when necessary.
4. Reload the entity from the repository.
5. Assert that the persisted state matches expectations.

A typical example is the owner/pet workflow:

- `ClinicServiceTests` loads an `Owner` from `OwnerRepository`.
- The test creates a new `Pet` or modifies an existing one.
- The owner aggregate is saved back through the repository.
- The test reloads the owner to confirm the database state changed.

This style is important because it tests not just Java object mutation, but also the JPA mapping details that make the domain model persist correctly.

## Data Model

The package exercises the following model relationships:

- `Owner` has a collection of `Pet` instances.
- `Pet` has a `PetType` and a collection of `Visit` instances.
- `Vet` has a collection of specialties.

The tests show that these relationships are expected to be hydrated from the database and preserved across save operations. They also show that ids are generated on insert and reused on subsequent reads.

```mermaid
flowchart TD
  Tests["ClinicServiceTests"] --> OwnerRepository["OwnerRepository"]
  Tests --> PetTypeRepository["PetTypeRepository"]
  Tests --> VetRepository["VetRepository"]
  Tests --> EntityUtils["EntityUtils"]
  OwnerRepository --> Owner["Owner"]
  Owner --> Pet["Pet"]
  Pet --> Visit["Visit"]
  Pet --> PetType["PetType"]
  VetRepository --> Vet["Vet"]
```

## Dependencies and Integration

This module depends on the following package areas:

- `org.springframework.samples.petclinic.owner` for the owner, pet, visit, and pet type domain model plus repositories
- `org.springframework.samples.petclinic.vet` for vet data and repository access
- `org.springframework.samples.petclinic.model` for the shared `BaseEntity` superclass
- `org.springframework.orm` for `ObjectRetrievalFailureException`
- Spring Boot test support through `@DataJpaTest` and test database configuration

The test class is intentionally narrow in scope: it does not test controllers or UI behavior. Its job is to prove that the persistence layer and entity mappings behave as expected.

## Notes for Developers

- Most tests assume preloaded reference data. If fixture data changes, the assertions may need to be updated.
- Several tests use hard-coded ids such as `1`, `3`, `6`, and `7`. Those ids are part of the expected test dataset, so changing seed data can break these tests.
- The transactional tests rely on Spring’s automatic rollback, which keeps database mutations isolated to each test method.
- `EntityUtils.getById(...)` throws `ObjectRetrievalFailureException` instead of returning `null`, so tests fail fast when a required entity is missing.
- When adding new persistence behavior, prefer extending this test suite with repository-focused integration tests rather than unit tests alone.
