# (DD07) Business Logic — OwnerControllerTests.processFindFormNoOwnersFound() [11 LOC]

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

## 1. Role

### OwnerControllerTests.processFindFormNoOwnersFound()

This method is a controller-level negative-path test that verifies the owner search workflow when the user searches by last name and the system returns no matching owners. It validates that the web layer does not proceed to an owner list or detail screen; instead, it keeps the user on the owner search page and attaches a business validation error to the `lastName` field. In business terms, this confirms the user experience for a failed owner lookup: the search request is accepted, the repository is queried, but the result set is empty and the UI must guide the user to revise the search criteria.

The method follows a request-stubbing-and-assertion pattern commonly used in MVC tests: it prepares an empty result page, configures the repository mock to return that result for a specific surname, performs the HTTP GET request, and verifies the model and view outcome. The only business scenario handled here is the "no owners found" branch of the owner search process. The method therefore acts as a quality gate for the controller’s validation behavior and search-result routing logic.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START["processFindFormNoOwnersFound()"]
    STEP1["Create empty PageImpl<Owner> result set"]
    STEP2["Stub owners.findByLastNameStartingWith('Unknown Surname', Pageable) to return empty page"]
    STEP3["Perform GET /owners?page=1 with lastName='Unknown Surname'"]
    COND1["Repository returns no owners?"]
    ASSERT1["Assert HTTP status is OK"]
    ASSERT2["Assert model has field error on owner.lastName"]
    ASSERT3["Assert field error code is notFound"]
    ASSERT4["Assert view is owners/findOwners"]
    END_NODE["Test completes"]

    START --> STEP1
    STEP1 --> STEP2
    STEP2 --> STEP3
    STEP3 --> COND1
    COND1 --> ASSERT1
    ASSERT1 --> ASSERT2
    ASSERT2 --> ASSERT3
    ASSERT3 --> ASSERT4
    ASSERT4 --> END_NODE
```

The test exercises a single controller branch: the owner repository returns an empty page for the requested surname, and the controller is expected to reject the search result at the UI level with a field error rather than navigating away.

## 3. Parameter Analysis

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

External state read by the method:
- `this.owners` mock repository: provides the search result for owner lookup by last name.
- `mockMvc`: performs the simulated HTTP request to the owner search endpoint.
- `Pageable` argument matcher: represents paged query input used by the controller’s search flow.
- Request parameter `lastName='Unknown Surname'`: the search criterion that drives the no-match scenario.

## 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.

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `OwnerRepository.findByLastNameStartingWith` | OwnerRepository | Owner | Reads owner records matching the supplied last-name prefix in a paged search query. |
| R | `mockMvc.perform` | MockMvc | HTTP Request / Owner Search Screen | Executes the controller request that triggers the owner search flow for the search page. |
| R | `status().isOk` | MockMvc ResultMatcher | HTTP Response | Verifies the controller returns an HTTP 200 response for the search page. |
| R | `model().attributeHasFieldErrors` | MockMvc ResultMatcher | Owner Form Model | Verifies the form model contains validation errors for the owner last-name field. |
| R | `model().attributeHasFieldErrorCode` | MockMvc ResultMatcher | Owner Form Model | Verifies the last-name field is marked with the expected `notFound` validation code. |
| R | `view().name` | MockMvc ResultMatcher | owners/findOwners View | Verifies the controller remains on the owner search view after no matches are found. |

## 5. Dependency Trace

Trace who calls this method and what this method ultimately calls.

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

## 6. Per-Branch Detail Blocks

**Block 1** — [TRY] `(test setup and execution)` (L158-L168)

> This block prepares the no-match owner search scenario and validates the controller response.

| # | Type | Code |
|---|------|------|
| 1 | SET | `Page<Owner> tasks = new PageImpl<>(List.of());` // create an empty search result page |
| 2 | CALL | `when(this.owners.findByLastNameStartingWith(eq("Unknown Surname"), any(Pageable.class))).thenReturn(tasks);` // stub repository search to return no owners |
| 3 | CALL | `mockMvc.perform(get("/owners?page=1").param("lastName", "Unknown Surname"))` // invoke owner search request |
| 4 | CALL | `.andExpect(status().isOk())` // assert successful HTTP response |
| 5 | CALL | `.andExpect(model().attributeHasFieldErrors("owner", "lastName"))` // assert last name field is rejected |
| 6 | CALL | `.andExpect(model().attributeHasFieldErrorCode("owner", "lastName", "notFound"))` // assert business validation code notFound |
| 7 | CALL | `.andExpect(view().name("owners/findOwners"));` // remain on the search page |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `Owner` | Entity | Pet owner domain record managed by the owner search and maintenance flow. |
| `OwnerRepository` | Repository | Data access component used to query owner records by last-name prefix. |
| `findByLastNameStartingWith` | Method | Search operation that returns owners whose last name begins with the supplied text. |
| `Page` | Technical term | Paged result container used to represent search results in the UI. |
| `PageImpl` | Technical term | Concrete pageable result implementation used to create an empty search result for testing. |
| `Pageable` | Technical term | Paging request descriptor that carries page and size information for the repository query. |
| `mockMvc` | Technical term | Spring MVC test harness used to simulate HTTP requests to the controller. |
| `lastName` | Field | Owner search criterion entered by the user to find matching owners. |
| `notFound` | Validation code | Error code indicating that the search did not match any owner records. |
| `owners/findOwners` | View | Owner search page shown when the lookup finds no matching owners. |
| `Unknown Surname` | Test data | Deliberately unmatched last-name value used to force the no-results branch. |
