Understanding CRUD
CRUD stands for Create, Read, Update, Delete — the four basic operations for persistent data storage. Nearly every API endpoint maps to one of these operations:
| CRUD | HTTP Method | Example | Typical Status |
|---|---|---|---|
| Create | POST | POST /users | 201 Created |
| Read | GET | GET /users/42 | 200 OK |
| Update | PUT / PATCH | PUT /users/42 | 200 OK |
| Delete | DELETE | DELETE /users/42 | 204 No Content |
Testing CRUD operations systematically ensures that the API correctly handles the entire lifecycle of a resource — from creation to deletion.
Testing Create (POST)
Happy Path Tests
POST /api/users
Content-Type: application/json
{
"name": "Alice Johnson",
"email": "alice@example.com",
"role": "developer"
}
Verify:
- Response status is 201 Created
- Response body contains the created resource with a generated
id - All submitted fields are present in the response
- Server-generated fields exist (
id,createdAt,updatedAt) - Location header points to the new resource URL
- Fetching the resource via GET returns the same data
Validation Tests
| Scenario | Expected |
|---|---|
| Missing required field (name) | 400 with clear error message |
Empty required field ("") | 400 with validation error |
| Invalid email format | 400/422 with format error |
| String where number expected | 400 with type error |
| Value exceeding max length | 400 with length error |
| Extra unknown fields | Ignored or 400 (depends on API design) |
Uniqueness Tests
| Scenario | Expected |
|---|---|
| Duplicate email | 409 Conflict |
| Duplicate name (if unique) | 409 Conflict |
Case sensitivity (alice@test.com vs Alice@test.com) | Depends on API design |
Boundary Tests
- Maximum field lengths (255 chars for name, etc.)
- Special characters: Unicode, emojis, HTML tags, SQL injection strings
- Minimum values: empty arrays, zero quantities
- Maximum payload size
Testing Read (GET)
Single Resource
GET /api/users/42
Verify:
- Returns 200 OK with complete user data
- All expected fields are present
- Data types are correct (number for id, string for name)
- Sensitive fields are excluded (password, internal IDs)
Collection (List)
GET /api/users?page=1&limit=20&sort=name&order=asc
Verify:
- Returns array of resources
- Pagination metadata is present (total, page, limit, pages)
- Sorting works correctly
- Filtering returns only matching resources
- Default pagination applies when no params sent
Edge Cases
| Scenario | Expected |
|---|---|
Non-existent ID (GET /users/99999) | 404 Not Found |
Invalid ID format (GET /users/abc) | 400 or 404 |
Negative ID (GET /users/-1) | 400 or 404 |
Page beyond results (?page=9999) | 200 with empty array |
Very large limit (?limit=100000) | Capped at max or 400 |
Testing Update (PUT / PATCH)
PUT — Full Replacement
PUT /api/users/42
Content-Type: application/json
{
"name": "Alice Smith",
"email": "alice.smith@example.com",
"role": "senior-developer"
}
Verify:
- All fields are replaced with new values
- Omitted optional fields are reset to defaults or removed
updatedAttimestamp changesidandcreatedAtremain unchanged- GET after PUT returns the updated data
PATCH — Partial Update
PATCH /api/users/42
Content-Type: application/json
{
"role": "senior-developer"
}
Verify:
- Only the specified field changes
- All other fields remain exactly as before
updatedAttimestamp changes
Update Edge Cases
| Scenario | Expected |
|---|---|
| Update non-existent resource | 404 Not Found |
| Update with invalid data | 400 with validation error |
| Update read-only fields (id, createdAt) | 400 or fields ignored |
| Concurrent updates (two PUTs simultaneously) | Last write wins or 409 |
| Update to duplicate unique value | 409 Conflict |
Testing Delete (DELETE)
Standard Delete
DELETE /api/users/42
Verify:
- Returns 204 No Content (or 200 OK with confirmation)
- GET for deleted resource returns 404
- Resource no longer appears in list endpoint
- Related resources are handled correctly (cascade or orphan protection)
Delete Edge Cases
| Scenario | Expected |
|---|---|
| Delete non-existent resource | 404 Not Found |
| Delete already-deleted resource | 404 Not Found |
| Delete resource with dependencies | 409 or cascade delete |
| Delete without authorization | 401/403 |
End-to-End CRUD Flow Test
The most important test is the complete lifecycle:
1. POST /users → Create user → Save ID
2. GET /users/{id} → Verify user exists with correct data
3. GET /users → Verify user appears in list
4. PUT /users/{id} → Update all fields
5. GET /users/{id} → Verify update applied
6. PATCH /users/{id} → Partial update one field
7. GET /users/{id} → Verify only that field changed
8. DELETE /users/{id} → Remove user
9. GET /users/{id} → Verify 404
10. GET /users → Verify user no longer in list
This flow tests data persistence, consistency, and cleanup across the entire lifecycle.
Data Relationships
When resources have relationships (user has many orders), test:
- Creating a child resource with valid parent ID
- Creating a child resource with invalid parent ID (should fail)
- Deleting a parent with existing children (cascade behavior)
- Fetching parent includes/excludes children as documented
- Updating parent does not affect child data
Hands-On Exercise
Using JSONPlaceholder (https://jsonplaceholder.typicode.com):
- Full CRUD lifecycle: Create a post, read it, update it with PUT, partial update with PATCH, delete it, verify deletion
- Validation testing: Try creating a post with missing fields, wrong types, empty values
- Relationship testing: Create a post, then create comments for that post. What happens when you delete the post?
- List testing: Test pagination, filtering by userId, and verify response structure for GET /posts
Key Takeaways
- CRUD operations form the backbone of API testing — every resource goes through create, read, update, delete
- Always verify data persistence by following POST with GET to confirm the resource actually exists
- Test both PUT (full replacement) and PATCH (partial update) to ensure they behave differently as expected
- End-to-end CRUD flow tests catch integration bugs that individual operation tests may miss
- Don’t forget edge cases: non-existent resources, duplicate entries, cascade deletes, and concurrent updates