Todo API lab
A to-do list API with six endpoints, and a collection of eight requests that test it. You will run the whole suite, read what each test proves, break the API on purpose, and add a test of your own.
Level: beginner · Time: about 30 minutes
Download
- todo-api.mockstudio.json — the mock API, for Mock Studio
- todo-api.apiworkbench.json — the requests and tests, for ApiWorkbench
Set up
In Mock Studio, select Import on the rail, choose Mock Studio project file and pick
todo-api.mockstudio.json. The project Todo API (sample) opens.Select Start server. The mock is now at
http://localhost:4010.In ApiWorkbench, select Import on the rail, choose
todo-api.apiworkbench.jsonand select Import. The collection Todo API (sample) appears under Collections.
The API
| Method | Path | What it does | Answers |
|---|---|---|---|
| GET | /health | Is the API up? | 200 |
| GET | /todos | List every todo | 200 |
| GET | /todos/:id | Read one todo | 200, or 404 for id 404 |
| POST | /todos | Create a todo | 201, or 400 without a title |
| PUT | /todos/:id | Replace a todo | 200 |
| DELETE | /todos/:id | Delete a todo | 204 |
A todo looks like this:
{ "id": 2, "title": "Send my first request", "done": false }It is a mock
The mock answers convincingly but does not remember. Create a todo and it will not appear in the list afterwards. That is normal for a mock, and it is why each test here checks one response, not stored state.
Step 1: send one request
Open Health check in the collection and select Send.
- The result bar shows 200 OK.
- The Pretty tab shows
"status": "ok"and the current time. - The response's Tests tab shows three passes.
Look at the URL: {{baseUrl}}/health. {{baseUrl}} is a variable. Its value, http://localhost:4010, is stored once on the collection, so all eight requests follow if the address changes. See Variables and environments.
Step 2: read the tests
Open the request's own Tests tab. Health check has three:
| Test | Expected | What it proves |
|---|---|---|
| Status equals | 200 | The API answered with success |
JSON field equals status | ok | The body says what it should, not only the status |
| Time below (ms) | 1000 | It answered within a second |
Three different kinds of evidence: the status, the content, the speed. A response can get the first right and the others wrong, which is why a single status check is never enough.
Step 3: run the whole suite
In Collections, open the ⋯ menu of Todo API (sample) and choose Run collection.
Select Run.
Watch the eight requests go by. Every one should pass: 22 checks in all.
Here is what the eight requests cover, and why each exists:
| Request | Kind of test | Checks |
|---|---|---|
| Health check | Smoke | Up, correct body, quick |
| List todos | Happy path | 200, JSON content type, first item's id, a known title |
| Get one todo | Happy path | 200, the id asked for, done is false |
| Get a todo that does not exist | Negative | 404 and an error field |
| Create a todo | Happy path | 201, title echoed, done false, a Location header |
| Create a todo without a title | Negative | 400 and an error field |
| Update the new todo | Chained | 200, new title, done true |
| Delete the new todo | Chained | 204 |
Half of a good suite is negative tests: sending something wrong and checking the API refuses correctly. See Negative testing.
Step 4: see how requests are chained
Open Create a todo, then its Captures tab:
newId = body.idAfter the response arrives, ApiWorkbench reads id from the body and stores it in a variable called newId. The next two requests use it in their URLs:
PUT {{baseUrl}}/todos/{{newId}}
DELETE {{baseUrl}}/todos/{{newId}}That is how a test follows a real journey: create something, then act on the thing that was just created. In the runner's results, the update and delete URLs show the real number. See Captures.
Step 5: break it, and watch the tests catch it
Tests earn their keep when something changes. Make a change in the mock and see what notices.
In Mock Studio, open Create todo and change the status of the Created response from
201to200.Run the collection again in ApiWorkbench.
Create a todo now fails:
expected 201, got 200.Put the status back to
201.
Try two more:
- In Health check, change
"status": "ok"to"status": "up". Which test fails, and which still pass? - In Get todo, add a delay of 1500 ms (see Latency and faults). Then add a Time below (ms) test of
1000to Get one todo and run again.
Every time, read the failure message. It says what was expected and what arrived.
Step 6: write your own
Add a search endpoint and test it.
In Mock Studio, add an endpoint: GET
/todos/search. Give it this body:json{ "query": "{{query.q}}", "results": [ { "id": 2, "title": "Send my first request", "done": false } ] }In ApiWorkbench, add a request to the collection: GET
{{baseUrl}}/todos/search, with a query parameterqset torequest.Add three tests: Status equals
200, JSON field equalsquery=request, and JSON field equalsresults[0].id=2.Send it, then run the collection. Nine requests, all passing.
Why did /todos/search not match /todos/:id?
Both paths fit the URL. Mock Studio picks the more specific one: a fixed word beats a parameter. See Endpoints and paths.
What you learned
- A collection plus tests is a repeatable check of a whole API.
- Check the status, the content and the time, not only the status.
- Negative tests prove the API refuses bad input properly.
- Captures carry a value from one response into the next request.
- A failing test tells you what changed.
Next steps
- Shop API lab: signing in, tokens and data files
- Functional testing
- Writing test cases