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

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

## 1. Role

### OwnerControllerTests.processFindFormNoOwnersFound()

This test method verifies the negative-path behavior of the owner search form when no matching owners are found for the requested last name. In business terms, it validates that the owner lookup entry point does not proceed to a results list when the search yields an empty result set, and instead preserves the search workflow by returning the user to the find form with validation feedback.

The method exercises the controller’s search-and-validate flow for owner discovery, specifically the branch where the repository returns no owners for the supplied surname. It confirms that the UI response is not a normal success result page, but a form view that shows a field-level error on `lastName` and uses the `notFound` error code to explain that the requested owner cannot be located. This is a test-only method and therefore acts as an executable specification for the business rule governing empty search results.

Architecturally, the method implements a routing/verification pattern: it prepares a stubbed repository response, drives the HTTP request through MockMvc, and asserts the controller’s branch selection and model state. Its role in the larger system is to safeguard the user-facing owner search experience and to ensure the controller continues to enforce the “no match” validation rule consistently.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START["processFindFormNoOwnersFound()"]
    SETUP["Create empty Page<Owner> result set"]
    STUB["Stub owners.findByLastNameStartingWith(\"Unknown Surname\", Pageable) to return empty page"]
    REQUEST["Perform GET /owners?page=1 with lastName=Unknown Surname"]
    ASSERT_OK["Assert HTTP status is OK"]
    ASSERT_FIELD["Assert owner.lastName has field errors"]
    ASSERT_CODE["Assert owner.lastName error code is notFound"]
    ASSERT_VIEW["Assert view name is owners/findOwners"]
    END_NODE["Return / Next"]

    START --> SETUP
    SETUP --> STUB
    STUB --> REQUEST
    REQUEST --> ASSERT_OK
    ASSERT_OK --> ASSERT_FIELD
    ASSERT_FIELD --> ASSERT_CODE
    ASSERT_CODE --> ASSERT_VIEW
    ASSERT_VIEW --> END_NODE
```

## 3. Parameter Analysis

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

This method takes no parameters. Its business behavior is determined entirely by local test fixtures, the mocked `owners` repository, and the fixed request data passed into MockMvc. External state read by the method includes the mocked `owners` dependency and the Spring MVC model/view state produced by the controller under test.

## 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 | `owners.findByLastNameStartingWith` | OwnerRepository | Owner | Reads owner records by last name prefix to simulate the empty-search scenario |
| R | `mockMvc.perform` | MockMvc | HTTP request / MVC pipeline | Executes the controller request path for owner search |
| R | `status().isOk` | MockMvc ResultMatcher | HTTP 200 | Verifies the request is handled successfully |
| R | `model().attributeHasFieldErrors` | MockMvc ResultMatcher | MVC model | Verifies field validation feedback is attached to `owner.lastName` |
| R | `model().attributeHasFieldErrorCode` | MockMvc ResultMatcher | MVC model | Verifies the validation code `notFound` is returned for the field error |
| R | `view().name` | MockMvc ResultMatcher | MVC view | Verifies the controller returns `owners/findOwners` |

## 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: `OwnerControllerTests` | `OwnerControllerTests.processFindFormNoOwnersFound` | `owners.findByLastNameStartingWith [R] Owner` |

## 6. Per-Branch Detail Blocks

### Block 1 — SEQUENCE (test setup and verification flow) (L159)

> This block covers the full negative-search test path from fixture setup through MVC assertions.

| # | Type | Code |
|---|------|------|
| 1 | SET | `Page<Owner> tasks = new PageImpl<>(List.of());` // create an empty result page for the no-match 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())` // expect HTTP success |
| 5 | CALL | `.andExpect(model().attributeHasFieldErrors("owner", "lastName"))` // expect a validation error on the lastName field |
| 6 | CALL | `.andExpect(model().attributeHasFieldErrorCode("owner", "lastName", "notFound"))` // expect the notFound error code |
| 7 | CALL | `.andExpect(view().name("owners/findOwners"));` // expect the search form view to be rendered again |
| 8 | RETURN | `return;` // test completes after assertions |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `Owner` | Domain entity | Pet owner record in the clinic system |
| `lastName` | Field | Owner surname used as the search key |
| `findByLastNameStartingWith` | Repository method | Searches owners by surname prefix |
| `notFound` | Validation code | Error code indicating that no matching owner was found |
| `findOwners` | View name | Owner search form screen |
| `MockMvc` | Test utility | Spring MVC test harness used to simulate HTTP requests |
| `Page<Owner>` | Pagination type | A paged collection of owner search results |
| `PageImpl` | Test fixture class | Concrete page implementation used to create an empty result set |
| `Pageable` | Framework type | Pagination request parameters for repository queries |
| `Unknown Surname` | Test data | Sample last name chosen to simulate a search that returns no matches |
| `owner` | Model attribute | MVC form-backing object for the owner search workflow |
| `HTTP 200 / OK` | Web response | Successful controller response status |
| `field errors` | Validation concept | Form-level validation feedback attached to a specific field |
