# Org / Springframework / Samples / Petclinic / Service

## Overview

The `org.springframework.samples.petclinic.service` package contains the integration tests that exercise the Petclinic service/repository layer and a small utility for working with persisted entities in tests. Although the package name suggests application services, the code here is specifically test support: it verifies that repository methods, entity relationships, and cascade behavior work together as expected.

This package exists to prove the persistence model behaves correctly under real database interaction. The tests cover lookup, insert, update, and relationship traversal for owners, pets, pet types, vets, and visits, while `EntityUtils` provides a simple way to locate a specific entity by id inside a loaded collection.

## Key Classes and Interfaces

### `ClinicServiceTests`

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

This is the main integration test class in the package. It is annotated with `@DataJpaTest`, so each test runs against a Spring-managed JPA context with repository beans wired in and database transactions rolled back by default. The class uses real repository interfaces rather than mocks, which makes it useful for validating mappings, query methods, and entity lifecycle behavior together.

The test class injects three repositories:

- `OwnerRepository` for owner and pet data
- `PetTypeRepository` for supported pet types
- `VetRepository` for veterinarian data

It also uses a shared `Pageable.unpaged()` instance for the repository query that returns paged results.

#### Important test methods

- `shouldFindOwnersByLastName()`
  - [source](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:87)
  - Calls `owners.findByLastNameStartingWith("Davis", pageable)` and verifies that two owners match.
  - Repeats the query with a misspelled prefix and checks that no owners are returned.
  - This confirms the repository query method performs prefix matching as expected.

- `shouldFindSingleOwnerWithPet()`
  - [source](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:96)
  - Loads owner id `1`, checks that it exists, and verifies the last name begins with `Franklin`.
  - Confirms that the owner has one pet and that the pet has a non-null type named `cat`.
  - This test validates eager/lazy loading behavior and the owner-to-pet-to-pet-type relationship.

- `shouldInsertOwner()`
  - [source](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:107)
  - Counts existing owners with last name prefix `Schultz`, creates a new `Owner`, and saves it through the repository.
  - Verifies that a generated id is assigned and that the count increases by one.
  - This confirms insert behavior and id generation.
  - The method is annotated with `@Transactional` so the insert is isolated and rolled back automatically.

- `shouldUpdateOwner()`
  - [source](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:126)
  - Loads owner id `1`, changes the last name, and saves the entity.
  - Reloads the owner from the database and checks that the updated value persisted.
  - This proves that repository save updates an existing row rather than creating a new one.
  - The test runs in a transaction to keep the database clean.

- `shouldFindAllPetTypes()`
  - [source](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:145)
  - Retrieves all pet types and looks up specific entries by id using `EntityUtils.getById(...)`.
  - Verifies that id `1` is `cat` and id `4` is `snake`.
  - This provides coverage for reference data and the utility lookup helper.

- `shouldInsertPetIntoDatabaseAndGenerateId()`
  - [source](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:155)
  - Loads owner id `6`, counts the owner's current pets, creates a new `Pet`, assigns a type, sets a birth date, and attaches it to the owner.
  - Saves the owner, reloads it, and verifies the pet count increased and the new pet received an id.
  - This is an important cascade-style persistence test: adding the pet through the aggregate root (`Owner`) should persist the child entity.
  - The `@Transactional` annotation keeps the database state temporary.

- `shouldUpdatePetName()`
  - [source](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:183)
  - Loads owner id `6`, retrieves pet id `7`, updates the pet name, and saves the owner.
  - Reloads the owner and verifies the new name persisted.
  - This confirms changes to nested entities are flushed when the owning aggregate is saved.

- `shouldFindVets()`
  - [source](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:204)
  - Loads all vets and uses `EntityUtils.getById(...)` to find vet id `3`.
  - Verifies last name, number of specialties, and the specialty names `dentistry` and `surgery`.
  - This test checks reference data and the vet-specialty relationship.

- `shouldAddNewVisitForPet()`
  - [source](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:215)
  - Loads owner id `6`, fetches pet id `7`, creates a new `Visit`, and adds it via `owner6.addVisit(pet7.getId(), visit)`.
  - Saves the owner and verifies that the visit count increases and that all visits have generated ids.
  - This test validates how new child records are added through domain helper methods on the aggregate root.

- `shouldFindVisitsByPetId()`
  - [source](src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java:235)
  - Loads owner id `6`, retrieves pet id `7`, and inspects its visits collection.
  - Verifies there are two visits and that the first visit has a non-null date.
  - This confirms the visit association is populated and that visit data is available through the pet relationship.

### `EntityUtils`

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

`EntityUtils` is a small abstract utility class used by the tests to find a specific entity in a loaded collection by id. It is separated from `BaseEntity` because it depends on `ObjectRetrievalFailureException`, which is tied to ORM-style retrieval semantics.

#### Method: `getById(Collection<T> entities, Class<T> entityClass, int entityId)`

Source: [src/test/java/org/springframework/samples/petclinic/service/EntityUtils.java:43](src/test/java/org/springframework/samples/petclinic/service/EntityUtils.java:43)

- **Purpose:** Search a collection for an entity whose id matches `entityId`.
- **Parameters:**
  - `entities` - the collection to search
  - `entityClass` - the expected entity type
  - `entityId` - the id to match
- **Returns:** the matching entity instance
- **Throws:** `ObjectRetrievalFailureException` if no matching entity is found

The implementation iterates over the collection, checks that each entity has a non-null id, compares the id value, and also confirms the runtime type with `entityClass.isInstance(entity)`. If a match is found, it is returned immediately. If not, the method throws `ObjectRetrievalFailureException(entityClass, entityId)`.

This helper keeps the tests readable when they need to assert against a specific entity inside a collection returned by a repository.

## How It Works

The package follows a straightforward integration-test pattern:

1. A repository method loads data from the database.
2. The test inspects the returned aggregate root or collection.
3. The test mutates an entity or adds a child entity.
4. The repository saves the aggregate root.
5. The test reloads the entity and verifies the change persisted.

The core design idea is to test the domain relationships through the real persistence layer rather than through isolated unit tests. That means the tests verify not only repository methods, but also entity mappings, cascade behavior, generated ids, and object graph traversal.

### Typical flow for an owner update

1. Load an owner with `owners.findById(1)`.
2. Change a simple field, such as `lastName`.
3. Save the owner back through `owners.save(owner)`.
4. Load the owner again from the database.
5. Assert the new value is present.

The same pattern is repeated for pets and visits, but with deeper object graphs.

### Typical flow for adding a pet or visit

- For a pet, the test creates a new `Pet`, sets its fields, resolves a `PetType`, and calls `owner.addPet(pet)`.
- For a visit, the test creates a new `Visit` and calls `owner.addVisit(petId, visit)`.
- In both cases, the owner is saved afterward so the ORM can persist the child entity.
- The test then reloads the owner and verifies the child was assigned an id and is visible in the collection.

### Relationship overview

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

## Data Model

The tests exercise a small set of domain entities from the Petclinic model:

- `Owner` - the aggregate root used for most write operations in this package
- `Pet` - owned by an owner and associated with a `PetType`
- `PetType` - lookup/reference data for pet categories
- `Visit` - appointment or treatment record attached to a pet
- `Vet` - veterinarian data, including specialties

The important modeling pattern is that `Owner` acts as the main persistence boundary for the owner/pet/visit workflow. Tests add pets and visits through owner helper methods instead of directly saving child entities, which suggests the domain model is designed around aggregate-style updates.

`EntityUtils.getById(...)` assumes all these entities inherit from `BaseEntity`, which provides the id property used throughout the tests.

## Dependencies and Integration

This package connects to the following modules and types:

- `org.springframework.samples.petclinic.owner`
  - `Owner`
  - `OwnerRepository`
  - `Pet`
  - `PetType`
  - `PetTypeRepository`
  - `Visit`
- `org.springframework.samples.petclinic.vet`
  - `Vet`
  - `VetRepository`
- `org.springframework.samples.petclinic.model`
  - `BaseEntity`
- Spring framework and test infrastructure
  - `@DataJpaTest` for a repository-focused test slice
  - `@Transactional` for automatic rollback on mutating tests
  - `@Autowired` for dependency injection
  - `Page` and `Pageable` for repository queries
  - `ObjectRetrievalFailureException` for lookup failures in the utility class

The test class is configured with `@AutoConfigureTestDatabase(replace = Replace.NONE)`, which indicates it should not automatically swap in an embedded test database. The comment in the file notes that when the mysql profile is active, the tests should connect to the real database.

## Notes for Developers

- These are integration tests, not isolated unit tests. They rely on repository behavior, entity mappings, and database state.
- Tests that mutate data are marked `@Transactional` so changes roll back automatically.
- Repository methods are exercised through real objects, so changes to mappings, cascade rules, or fetch strategy can break these tests even if repository signatures stay the same.
- `EntityUtils.getById(...)` throws if an entity is missing, which is helpful for keeping test failures explicit and close to the source of the problem.
- Several tests assume fixture data already exists in the database, such as owner ids `1` and `6`, pet id `7`, and vet id `3`. If that seed data changes, the tests will fail and likely need to be updated together.
- When adding new behavior in this package, follow the existing pattern: load a real entity, mutate the object graph, save through the aggregate root, and verify by reloading from the repository.

