---

# (DD37) Business Logic — ClinicServiceTests.shouldFindOwnersByLastName() [8 LOC]

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

## 1. Role

### ClinicServiceTests.shouldFindOwnersByLastName()

This test method validates the owner search capability exposed through the service test fixture by exercising the repository-style lookup for owners whose last name begins with a supplied prefix. In business terms, it confirms that the owner directory can return a paged result set for a common customer-service use case: finding pet owners by surname when the exact spelling is known only partially. The method covers two outcome categories: a successful search where the prefix `Davis` returns two matching owners, and a negative search where the non-matching prefix `Daviss` returns no owners. The pattern is a direct delegation-and-assertion test, where the method invokes the data access operation and then verifies that the returned collection size matches the expected business outcome. Within the larger system, this method serves as a regression check for search behavior that supports owner lookup screens and downstream workflows such as pet and visit management.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["shouldFindOwnersByLastName()"])
    CALL1["Call this.owners.findByLastNameStartingWith(\"Davis\", pageable)"]
    ASSERT1["Verify returned Page has size 2"]
    CALL2["Call this.owners.findByLastNameStartingWith(\"Daviss\", pageable)"]
    ASSERT2["Verify returned Page is empty"]
    END_NODE(["Return"])
    START --> CALL1
    CALL1 --> ASSERT1
    ASSERT1 --> CALL2
    CALL2 --> ASSERT2
    ASSERT2 --> END_NODE
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| - | (none) | - | - |

This method declares no parameters. Its behavior is driven by local test setup state, specifically the injected `owners` repository reference and the shared `pageable` test fixture used to request paged owner search results.

## 4. CRUD Operations / Called Services

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

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `OwnerRepository.findByLastNameStartingWith` | OwnerRepository | Owner | Calls `findByLastNameStartingWith` in `OwnerRepository` |

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 | `findByLastNameStartingWith` | OwnerRepository | Owner | Retrieves a paged list of owners whose last name starts with the supplied prefix |

## 5. Dependency Trace

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Test: `ClinicServiceTests` | `ClinicServiceTests.shouldFindOwnersByLastName` -> `OwnerRepository.findByLastNameStartingWith` | `findByLastNameStartingWith [R] Owner` |
| 2 | Screen: `OwnerController` | `OwnerController` -> `OwnerRepository.findByLastNameStartingWith` | `findByLastNameStartingWith [R] Owner` |
| 3 | Test: `OwnerControllerTests` | `OwnerControllerTests` -> `OwnerRepository.findByLastNameStartingWith` | `findByLastNameStartingWith [R] Owner` |

**Instructions:**
- Use `search_files` with pattern `**/*.java` and content_pattern `shouldFindOwnersByLastName` to find all callers.
- For each caller, identify if it's a Screen (class name contains `KKSV*`, `Screen*`), Batch, Controller, or CBS.
- Build the full call chain from the entry point to this method.
- Each row = one unique entry point. Show ALL found callers (up to 15 rows).
- The Terminal column lists ALL CRUD endpoints reached FROM this method.
- Format terminal as: `methodName [C/R/U/D] EntityOrTableName`
- If a caller class name matches `KKSV\d{4}`, format as `Screen:KKSVxxxx`.

## 6. Per-Branch Detail Blocks

**Block 1** — [EXEC] `(invoke owner search)` (L87-L92)

> This block covers the single execution path of the test: it calls the owner search repository twice and verifies the paging results.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `Page<Owner> owners = this.owners.findByLastNameStartingWith("Davis", pageable);` |
| 2 | CALL | `this.owners.findByLastNameStartingWith("Davis", pageable);` |
| 3 | CALL | `assertThat(owners).hasSize(2);` |
| 4 | EXEC | `owners = this.owners.findByLastNameStartingWith("Daviss", pageable);` |
| 5 | CALL | `this.owners.findByLastNameStartingWith("Daviss", pageable);` |
| 6 | CALL | `assertThat(owners).isEmpty();` |
| 7 | RETURN | `return;` |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `Owner` | Domain entity | Pet owner record stored in the application directory |
| `owners` | Repository field | Data access component used to search owner records |
| `lastName` | Field | Owner surname used as the search key |
| `findByLastNameStartingWith` | Repository method | Lookup that returns all owners whose last name begins with the provided prefix |
| `Page` | Technical term | Paginated result container for search results |
| `Pageable` | Technical term | Pagination and sorting request used to control result slicing |
| `Davis` | Test data | Expected matching surname prefix returning two owners in the fixture data |
| `Daviss` | Test data | Non-matching surname prefix used to verify empty search behavior |
