# (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 test verifies the negative-path behavior of the Owner search flow when a user searches by last name and the repository returns no matching owners. From a business perspective, it confirms that the owner lookup screen does not silently succeed when the requested customer record cannot be found; instead, the controller must preserve the search form, mark the `lastName` field as invalid, and return the user to the owner search page with an explicit validation error.

The method also validates the controller's response contract for an empty result set: the HTTP request must complete successfully, the model must contain a field-level error with code `notFound`, and the view must remain `owners/findOwners`. In the larger system, this test protects the owner search entry point from regressions in the UX and ensures the application gives a clear, business-readable message when no owner record matches the supplied surname.

Functionally, the method implements a test harness pattern rather than business routing itself. It prepares a stubbed repository result, drives the MVC endpoint through `MockMvc`, and asserts the controller's branch selection for the zero-results scenario. This makes it a regression guard for the search-and-validate branch of the Owner controller.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["processFindFormNoOwnersFound()"])
    SETUP["Create empty PageImpl for owner search result"]
    STUB["Stub owners.findByLastNameStartingWith('Unknown Surname', Pageable) to return empty page"]
    REQUEST["Execute GET /owners?page=1 with lastName='Unknown Surname'"]
    ASSERT_STATUS["Assert HTTP status is 200 OK"]
    ASSERT_MODEL_ERRORS["Assert model has field error on owner.lastName"]
    ASSERT_ERROR_CODE["Assert field error code is notFound"]
    ASSERT_VIEW["Assert view is owners/findOwners"]
    END_NODE(["Return / Next"])

    START --> SETUP
    SETUP --> STUB
    STUB --> REQUEST
    REQUEST --> ASSERT_STATUS
    ASSERT_STATUS --> ASSERT_MODEL_ERRORS
    ASSERT_MODEL_ERRORS --> ASSERT_ERROR_CODE
    ASSERT_ERROR_CODE --> ASSERT_VIEW
    ASSERT_VIEW --> END_NODE
```

## 3. Parameter Analysis

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

External state read by this method:
- `this.owners` — mocked owner repository used to simulate the search result.
- `MockMvc mockMvc` — Spring MVC test driver used to invoke the controller endpoint.
- `Pageable` — resolved implicitly by the controller request mapping during search execution.
- Search input values `lastName = 'Unknown Surname'` and `page = 1` — business criteria for the owner lookup.

## 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 |
|------|----------|---------|-------------|----------------------|
| C | `new PageImpl<>(List.of())` | N/A | N/A | Creates an in-memory empty page to simulate no matching owners |
| R | `owners.findByLastNameStartingWith` | OwnerRepository | Owner | Reads owner records by surname prefix and returns an empty result set |
| R | `mockMvc.perform` | MockMvc | OwnerController endpoint | Executes the HTTP search request against the controller under test |
| R | `status().isOk` | MockMvc assertion | HTTP response | Verifies the endpoint returns a successful response |
| R | `model().attributeHasFieldErrors` | MockMvc assertion | owner.lastName validation state | Verifies the controller flags the lastName field as invalid |
| R | `model().attributeHasFieldErrorCode` | MockMvc assertion | owner.lastName validation state | Verifies the validation error code is `notFound` |
| R | `view().name` | MockMvc assertion | View name | Verifies the controller routes back to the owner search page |

## 5. Dependency Trace

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

## 6. Per-Branch Detail Blocks

**Block 1** — Sequential setup and assertion flow `(L158-L168)`

> This method contains a single straight-line test scenario with no conditional branching. It simulates the no-match search outcome and then verifies the controller response.

| # | Type | Code |
|---|------|------|
| 1 | SET | `Page<Owner> tasks = new PageImpl<>(List.of());` // Create an empty result page for the search scenario |
| 2 | CALL | `when(this.owners.findByLastNameStartingWith(eq("Unknown Surname"), any(Pageable.class))).thenReturn(tasks);` // Stub repository to return no owners |
| 3 | CALL | `mockMvc.perform(get("/owners?page=1").param("lastName", "Unknown Surname"))` // Invoke the owner search endpoint |
| 4 | CALL | `.andExpect(status().isOk())` // Verify HTTP 200 response |
| 5 | CALL | `.andExpect(model().attributeHasFieldErrors("owner", "lastName"))` // Verify validation error on lastName |
| 6 | CALL | `.andExpect(model().attributeHasFieldErrorCode("owner", "lastName", "notFound"))` // Verify business error code notFound |
| 7 | CALL | `.andExpect(view().name("owners/findOwners"));` // Verify the controller returns the search form view |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `Owner` | Domain entity | A pet owner record in the Petclinic application |
| `lastName` | Field | Owner surname used as the primary search key in the find-owner flow |
| `notFound` | Validation code | Business error code indicating that no matching owner record was found |
| `owners/findOwners` | View | Owner search page shown to users when searching for an owner |
| `MockMvc` | Test tool | Spring MVC test harness used to simulate HTTP requests and verify controller behavior |
| `Page` | Technical type | Paginated result container returned by the repository |
| `PageImpl` | Technical type | Concrete in-memory implementation of a paginated result |
| `Pageable` | Technical type | Pagination and sorting request metadata supplied to repository queries |
| `findByLastNameStartingWith` | Repository method | Searches for owners whose last name begins with the supplied text |
| `Unknown Surname` | Test data | Synthetic input value used to drive the no-results branch |
| `model` | MVC concept | The data map exposed to the rendered view and validation framework |
| `view` | MVC concept | Logical page name returned by the controller after processing the search request |
