# (DD30) Business Logic — ClinicServiceTests.shouldAddNewVisitForPet() [19 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `org.springframework.samples.petclinic.service.ClinicServiceTests` |
| Layer | Service Test |
| Module | `service` (Package: `org.springframework.samples.petclinic.service`) |

## 1. Role

### ClinicServiceTests.shouldAddNewVisitForPet()

This test verifies the business rule that a new medical visit can be attached to an existing pet and that the change is durably reflected when the owning aggregate is saved. In practical terms, it simulates a clinic workflow where a staff member records a new visit note for a pet that already exists under a known owner record. The method exercises the owner aggregate behavior by loading an owner, locating a specific pet, creating a new `Visit`, and delegating the association logic to the domain model rather than manipulating visit state directly.

The method primarily covers the pet-visit registration flow for a single visit type: a newly created visit with a simple description. It uses a routing-by-aggregate pattern in which the owner object is the entry point for locating a pet, the pet is the container for visits, and persistence is finalized through the repository save operation. The test does not branch into multiple service categories, but it does validate two business outcomes: the visit collection grows by one item, and each visit in the collection has been assigned an identifier after persistence. Within the larger system, this test acts as a regression guard for the owner/pet/visit aggregate boundary and confirms that the JPA cascade and domain association behavior remain intact.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["shouldAddNewVisitForPet()"])
    A(["Read owner by id 6 via owners.findById(6)"])
    B{"Owner present?"}
    C(["Unwrap Optional to owner6"])
    D(["Load pet 7 via owner6.getPet(7)"])
    E(["Count current visits on pet7"])
    F(["Create new Visit object"])
    G(["Set visit description to test"])
    H(["Add visit to pet via owner6.addVisit(pet7.getId(), visit)"])
    I(["Persist owner via owners.save(owner6)"])
    J(["Assert visit collection size increased by 1"])
    K(["Assert every visit has a non-null id"])
    END_NODE(["End"])
    START --> A
    A --> B
    B -->|Yes| C
    B -->|No| END_NODE
    C --> D
    D --> E
    E --> F
    F --> G
    G --> H
    H --> I
    I --> J
    J --> K
    K --> END_NODE
```

The test starts by reading an owner record with id `6`, then checks that the returned `Optional` contains data before unwrapping it. After that, it retrieves pet `7` from the owner aggregate and captures the current visit count as a baseline. The test then creates a fresh `Visit`, sets its description to `test`, adds the visit to the selected pet through the owner domain method, and persists the owner back through the repository. Finally, it validates that the visit count increased by one and that all visits in the pet now have non-null identifiers, proving the persistence cascade and aggregate linkage worked end to end.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| - | (none) | - | This test method accepts no parameters. It operates entirely from repository access and hard-coded test fixture identifiers to validate the owner-pet-visit registration flow. |

Instance fields and external state used by the method:
- `this.owners` — owner repository used to load and save the aggregate.
- Persistent test data — owner id `6` and pet id `7` from the preloaded test dataset.
- JPA persistence context — required so the visit collection and generated identifiers are visible after save.

## 4. CRUD Operations / Called Services

### Pre-computed evidence from code analysis graph:

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `owners.findById` | OwnerRepository | Owner | Reads an owner aggregate by primary key to locate the test fixture owner. |

Analyze all method calls within this method and classify each as a CRUD operation.
Use the pre-computed evidence above. If SC Code or Entity/DB is missing, try to infer from:
- The **SC Code** (Service Component code, e.g., `EKK0361A010SC`, `EKK1081D010CBS`) — look at the class name of the called method or its containing class.
- The **Entity/DB tables** — search for table name constants (often `KK_T_*` pattern), SQL references, or entity names in the called method's source code.

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `owners.findById` | OwnerRepository | Owner | Reads the owner aggregate for the predefined owner id `6`. |
| C | `new Visit()` | N/A | Visit | Creates a new visit domain instance for the pet. |
| U | `visit.setDescription` | N/A | Visit | Sets the visit description field to the test value `test`. |
| C | `owner6.addVisit` | N/A | Owner / Pet / Visit | Adds the new visit to the selected pet within the owner aggregate. |
| C | `owners.save` | OwnerRepository | Owner, Pet, Visit | Persists the updated owner aggregate and cascades the new visit record. |
| R | `pet7.getVisits()` | N/A | Visit collection | Reads the current visit collection to capture the baseline size. |
| R | `pet7.getId()` | N/A | Pet | Reads the pet identifier for the add-visit association. |
| R | Assertion on `pet7.getVisits()` | N/A | Visit collection | Verifies the resulting visit collection size and generated identifiers. |

## 5. Dependency Trace

Trace who calls this method and what this method ultimately calls.
Use the pre-computed evidence and caller search results from Step 2 above.

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Test runner / JUnit | `JUnit engine` -> `ClinicServiceTests.shouldAddNewVisitForPet` | `owners.findById [R] Owner` |
| 2 | Test runner / JUnit | `JUnit engine` -> `ClinicServiceTests.shouldAddNewVisitForPet` | `owner6.addVisit [C] Owner / Pet / Visit` |
| 3 | Test runner / JUnit | `JUnit engine` -> `ClinicServiceTests.shouldAddNewVisitForPet` | `owners.save [C] Owner, Pet, Visit` |

## 6. Per-Branch Detail Blocks

**Block 1** — [SEQUENCE] `(linear test setup and verification)` (L217-L233)

> This test executes as a straight-line validation scenario without conditional business branching in the method body.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `this.owners.findById(6);` // load owner fixture |
| 2 | CALL | `assertThat(optionalOwner).isPresent();` // verify the owner record exists |
| 3 | SET | `Owner owner6 = optionalOwner.get();` // unwrap owner fixture |
| 4 | CALL | `owner6.getPet(7);` // locate pet fixture under the owner |
| 5 | SET | `int found = pet7.getVisits().size();` // capture current visit count baseline |
| 6 | SET | `Visit visit = new Visit();` // create a new visit record |
| 7 | CALL | `visit.setDescription("test");` // assign visit description |
| 8 | CALL | `owner6.addVisit(pet7.getId(), visit);` // attach visit to the selected pet |
| 9 | CALL | `this.owners.save(owner6);` // persist owner aggregate and cascade visit |
| 10 | CALL | `assertThat(pet7.getVisits())` // inspect resulting visits collection |
| 11 | CALL | `.hasSize(found + 1)` // verify one visit was added |
| 12 | CALL | `.allMatch(value -> value.getId() != null);` // verify generated identifiers exist |
| 13 | RETURN | `return;` // test method completes successfully |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `owners` | Repository | Owner repository used to load and persist the owner aggregate. |
| `Owner` | Entity | A clinic customer who owns one or more pets. |
| `Pet` | Entity | An animal owned by a customer and eligible for visits. |
| `Visit` | Entity | A clinic visit record attached to a specific pet. |
| `addVisit` | Domain method | Adds a visit to the selected pet through the owner aggregate boundary. |
| `findById` | Repository method | Retrieves a persisted owner by primary key. |
| `save` | Repository method | Persists the owner aggregate and cascades related changes. |
| `Optional` | Technical type | Wrapper indicating the owner may or may not exist in the repository result. |
| `JPA` | Acronym | Java Persistence API — object-relational persistence used for entity storage. |
| `cascade` | Persistence term | Automatic propagation of save operations from owner to nested pet and visit entities. |
| `fixture` | Test term | Preloaded test data used to make the test deterministic. |
| `identifier` | Business/technical term | Primary key assigned by persistence to a visit or entity record. |
| `JUnit` | Testing framework | Unit and integration test runner executing the method. |
| `repository` | Data access term | Abstraction used to query and store domain entities. |
