---
# (DD05) Business Logic — OwnerControllerTests.processUpdateOwnerFormHasErrors() [13 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.processUpdateOwnerFormHasErrors()

This test verifies the owner update submission path when the user provides incomplete or invalid contact information. It exercises the web layer endpoint for editing an existing owner and confirms that validation failures on required form fields are surfaced back to the same owner form rather than allowing an update to proceed. In business terms, it protects the owner maintenance workflow from accepting an update that would leave the customer record missing mandatory address and telephone information.

The method specifically targets the negative branch of the owner update operation, where Spring MVC binding and validation detect field-level errors. It asserts that the application returns the owner creation/update view, keeps the user on the form screen, and exposes validation messages for the address and telephone fields. This is a test-oriented method, so its design pattern is assertion-based verification of controller behavior through MockMvc rather than production routing or delegation.

Within the larger system, this method serves as a regression guard for the owner edit screen. It ensures that the controller’s validation contract remains stable when form data is incomplete, and it indirectly verifies the user experience expected by the UI team: invalid edits should not be persisted and should be redisplayed for correction.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["processUpdateOwnerFormHasErrors(mockMvc POST /owners/{ownerId}/edit)"])
    REQ(["Submit owner update form with firstName, lastName, empty address, empty telephone"])
    POST(["MockMvc.perform(post('/owners/{ownerId}/edit', TEST_OWNER_ID))"])
    VALIDATE(["Spring MVC binds request to Owner and runs validation"])
    ERRORS{"BindingResult hasErrors()?"}
    KEEP_FORM(["Return owners/createOrUpdateOwnerForm view"])
    ASSERT_OK(["Expect HTTP 200 OK"])
    ASSERT_MODEL(["Expect owner model has validation errors"])
    ASSERT_ADDRESS(["Expect address field error"])
    ASSERT_TELEPHONE(["Expect telephone field error"])
    END_NODE(["Test passes"])

    START --> REQ
    REQ --> POST
    POST --> VALIDATE
    VALIDATE --> ERRORS
    ERRORS -- "yes - invalid address and telephone" --> KEEP_FORM
    KEEP_FORM --> ASSERT_OK
    ASSERT_OK --> ASSERT_MODEL
    ASSERT_MODEL --> ASSERT_ADDRESS
    ASSERT_ADDRESS --> ASSERT_TELEPHONE
    ASSERT_TELEPHONE --> END_NODE
    ERRORS -- "no" --> END_NODE
```

## 3. Parameter Analysis

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

This method does not declare parameters. It reads shared test state from the `MockMvc` field, the `TEST_OWNER_ID` constant, and the mocked `owners` repository configured in `@BeforeEach` to supply the existing owner record used by the controller test.

## 4. CRUD Operations / Called Services

This method does not call business services directly. It performs an HTTP POST through `MockMvc`, which triggers controller binding and validation for the owner update screen. The observable behavior under test is a failed update validation path, so no Create, Read, Update, or Delete persistence operation is expected from this method itself.

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `MockMvc.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID))` | N/A | `Owner` form binding | Submits the owner edit request and invokes the controller validation path |
| R | `model().attributeHasErrors("owner")` | N/A | `Owner` model | Verifies that validation errors are attached to the owner form model |
| R | `model().attributeHasFieldErrors("owner", "address")` | N/A | `Owner.address` | Verifies address is rejected as missing or invalid |
| R | `model().attributeHasFieldErrors("owner", "telephone")` | N/A | `Owner.telephone` | Verifies telephone is rejected as missing or invalid |

## 5. Dependency Trace

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Screen: `OwnerControllerTests` | `OwnerControllerTests.processUpdateOwnerFormHasErrors` | `MockMvc POST /owners/{ownerId}/edit` [R] `Owner` form binding |

The test method is an entry point from the JUnit runner rather than from a production screen or batch flow. Its downstream dependency is the controller update endpoint, which is invoked indirectly through MockMvc and validated by assertions on the resulting model and view state.

## 6. Per-Branch Detail Blocks

**Block 1** — [SEQUENCE] `(test setup and request submission)` (L203-L210)

> This block builds a simulated owner-edit submission with missing required fields and sends it to the controller endpoint.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `mockMvc.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID).param("firstName", "Joe").param("lastName", "Bloggs").param("address", "").param("telephone", ""))` |

**Block 2** — [ASSERT] `(response status and validation outcome)` (L211-L214)

> This block verifies that the controller returns the form view with field-level validation errors instead of redirecting to the detail page.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `.andExpect(status().isOk())` |
| 2 | CALL | `.andExpect(model().attributeHasErrors("owner"))` |
| 3 | CALL | `.andExpect(model().attributeHasFieldErrors("owner", "address"))` |
| 4 | CALL | `.andExpect(model().attributeHasFieldErrors("owner", "telephone"))` |
| 5 | CALL | `.andExpect(view().name("owners/createOrUpdateOwnerForm"))` |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `MockMvc` | Technical term | Spring test harness used to simulate HTTP requests to the web layer |
| `owner` | Domain entity | Pet owner record maintained by the application |
| `firstName` | Field | Owner given name captured on the edit form |
| `lastName` | Field | Owner family name captured on the edit form |
| `address` | Field | Owner mailing address; required for a valid owner update |
| `telephone` | Field | Owner contact number; required for a valid owner update |
| `ownerId` | Field | Identifier used in the URL to target the owner being edited |
| `BindingResult` | Technical term | Spring object that collects validation and binding errors |
| `validation` | Technical term | Automatic checks that ensure submitted form values meet required rules |
| `owners/createOrUpdateOwnerForm` | View | UI screen used for both owner creation and owner editing |
| `HTTP 200 OK` | Technical term | Successful response that re-renders the form without redirecting |
| `JUnit` | Technical term | Test framework used to execute the method |
| `Spring MVC` | Technical term | Web framework layer handling controller binding and request processing |
| `CRUD` | Acronym | Create, Read, Update, Delete — standard data operation categories |
| `regression guard` | Business term | Test coverage that prevents previously working validation behavior from breaking |
| `form binding` | Technical term | Process of mapping HTTP request parameters into the `Owner` object |
| `redirect` | Technical term | HTTP response that sends the user to another URL after a successful update |
