🏷️ B2 · Model/Entity: Bug class, enums, field types

B2 · Model/Entity: Bug class, enums: The model class is the API's **dictionary**: it defines in one place what a "bug" means — which fields it has, each field's type, which value

The model class is the API's **dictionary**: it defines in one place what a "bug" means — which fields it has, each field's type, which values are valid. Using an **enum** (LOW/MEDIUM/HIGH/CRITICAL) for `severity` instead of free text means "only these four words are accepted". But why not leave it `String severity` — isn't that more flexible? Because flexibility here is a trap: as a `String`, one writes `"critical"`, another `"Critical"`, another `"urgent"`, and reports, filters, and prioritization all break — an enum rejects an invalid value right at the gate (during deserialization). In Java the equivalent is the `enum` type itself; the type system makes an invalid state impossible at compile/parse time (Core Java's "make illegal states unrepresentable"). In QA the model is the map for producing test data: which field is required, which enum values are valid, which format (email, ISO date) is expected — you derive your negative tests (invalid enum, malformed date) from it.

The Bug Model and Enums

**🐞 Defect Birth — if `severity` is left a `String` instead of an enum** **Code:** `private String severity;` (NOT an enum). **What happens:** `POST /api/v1/bugs { "severity": "urgent" }` returns 201 instead of 400; an invalid priority is written to the database. A day later the "fetch critical bugs" filter (`severity == "CRITICAL"`) MISSES this record — a critical bug never appears on the report screen. **Why sneaky:** the record is created successfully (201), the UI lists it, there is no error. The problem surfaces only when a filter/report runs, and silently: a mistyped priority becomes a "ghost record". **Where the tester catches it:** in a negative test — sending an invalid `severity` (`"urgent"`, `"critical"`, `"5"`) and getting 201 while expecting 400. As an enum, the server would reject the value during deserialization.

🎬 Enum or String? The Ghost Record of an Invalid Priority

A request arrives with an invalid priority: `severity: "urgent"` — not one of the four valid values. What happens depends on the model.

If the model is an enum: deserialization acts like a gate, "urgent" is unrecognized, and the request is REJECTED with 400. Invalid data never gets in.

But if the model is a String there is NO gate: "urgent" is accepted as-is and written to the database. The request returns 201 — the problem is invisible.

The next day — the "fetch critical bugs" filter looks for `severity == "CRITICAL"`; it MISSES the "urgent" record. A critical bug is absent from the report.

The lesson — An enum makes an invalid state impossible at the gate. The tester hunts it with a negative test: send an invalid enum, expect 400. A String model removes that gate.

The Model Is the Map for Test Data

Find required fields…

From the model you see title is required → a "POST without title" negative test is born.

severity has 4 valid values → "invalid enum" tests (urgent, 5, empty) derive from here.

reporter is email, createdAt is ISO-8601 → malformed-format negative tests are read from the model.