Skip to content

Shop API lab ​

A small shop: sign in, browse products, place and cancel orders. This lab covers the things real API testing is made of: tokens, requests that depend on each other, one request run with many inputs, and load.

Level: intermediate · Time: about 45 minutes · Before this: Todo API lab

Download ​

Set up ​

  1. In Mock Studio, select Import, choose Mock Studio project file and pick shop-api.mockstudio.json. Select Start server. The mock is at http://localhost:4020.

  2. In ApiWorkbench, select Import, choose shop-api.apiworkbench.json and select Import.

The API ​

MethodPathNeeds a tokenAnswers
POST/auth/loginNo200 with a token, or 401
GET/meYes200, or 401
GET/productsNo200. ?category=books filters
GET/products/:idNo200, or 404 for id 999
POST/ordersYes201, 400 (fields missing), 422 (quantity over 10), or 401
GET/orders/:idYes200, or 401
DELETE/orders/:idYes204, or 401

The only account is ada@example.com with the password secret123. Both are made up and exist only in this mock.

Part 1: sign in and carry the token ​

  1. Open Auth › Sign in and look at the Body tab:

    json
    {
      "email": "{{email}}",
      "password": "{{password}}"
    }

    The values come from collection variables, so the credentials are written in one place.

  2. Open the Captures tab:

    text
    token = body.token
  3. Select Send. The response has a token, and the capture stores it in a variable named token.

  4. Open Auth › Who am I and look at the Auth tab: the type is Bearer Token and the token is {{token}}.

  5. Select Send. You get 200 and Ada's profile.

Now open Who am I, without a token and send it. 401. The same endpoint, the same URL; the only difference is the missing Authorization header. That request is a test in its own right: it proves the endpoint is protected.

Order matters

Requests that use {{token}} only work after Sign in has run. In the runner that happens by itself, because Sign in comes first. See Captures.

Part 2: how the mock decides ​

In Mock Studio, open Auth › Login. It uses Conditional rules, with two responses:

ResponseConditionsStatus
Signed inBody field email equals ada@example.com and password equals secret123200
Wrong email or passwordNone: the fallback401

Responses are checked top to bottom. The first whose conditions all match is sent; a response with no conditions is the fallback.

Orders › Create order has three, and their order matters:

ResponseConditionsStatus
Quantity too largequantity greater than 10422
CreatedproductId exists and quantity exists201
Fields missingNone: the fallback400

If Created came first, an order for 50 would match it and never reach the 422 rule. Put the most specific rule first. See Conditional rules.

The token requirement is separate: Create order has Require auth header turned on, so any request without an Authorization header gets a 401 before the rules are looked at.

Part 3: run the whole journey ​

Open the collection's ⋯ menu, choose Run collection, and select Run. Thirteen requests run in order and all pass.

Follow the thread through the Orders folder:

  1. Place an order creates an order and captures orderId = body.id.
  2. Check the order reads /orders/{{orderId}}.
  3. Cancel the order deletes /orders/{{orderId}}.

Three requests, two captured values (token and orderId), one user journey. That is a workflow test: see Workflow testing.

Part 4: one request, many inputs ​

Place an order sends this body:

json
{
  "productId": {{productId}},
  "quantity": {{quantity}}
}

Normally productId and quantity come from the collection variables (1 and 2). In a data-driven run they come from a file instead, one row per pass. Open shop-orders.csv:

csv
productId,quantity,expectedStatus
1,1,201
2,3,201
3,10,201
1,11,422
2,50,422

Five orders: three that should succeed, and two that are over the limit of 10 and should be refused. Row 3 and row 4 sit either side of the limit on purpose. That is boundary testing.

  1. Open the ⋯ menu of the Orders folder and choose Run folder.

  2. In the runner, select Load data file and pick shop-orders.csv. The preview shows five rows.

  3. Select Run. The folder runs five times, once per row.

The first pass needs a token

Run Auth › Sign in once before running the Orders folder by itself, so that token has a value. Or run the whole collection with the data file.

How does the test know that row 4 should get a 422? A no-code test has one fixed expected value, so this request uses a short script instead. Open Place an order › Scripts, and look at the post-response script:

js
const expected = Number(pm.iterationData.get('expectedStatus') || 201);
pm.test('status is ' + expected, function () {
  pm.response.to.have.status(expected);
});

It reads expectedStatus from the current row and checks the response against it. Without a data file there is no row, so it expects 201. See Data-driven runs and Scripts.

Try it: add a row 1,0,201 to the CSV and run again. The mock accepts a quantity of zero. Should a real shop? You have found a missing rule, which is what boundary tests are for.

Part 5: load the mock with a flow ​

The Mock Studio project includes a flow: a journey run by several virtual users at once.

  1. In Mock Studio, open Flows on the rail and select Checkout journey.

  2. Read its four steps: Sign in, Browse products, Place an order, Check the order. The first extracts token = body.token; later steps send Authorization: Bearer {{vars.token}}.

  3. Note the load profile: 5 virtual users, 10 iterations each, a 2 second ramp-up and 100 ms of think time. That is 200 requests.

  4. Select Run flow.

The results show requests per second, the error rate, and p50, p95 and p99 response times for each step. Against a mock on your own machine they will be a few milliseconds; the point is to learn to read them. Load testing explains what the percentiles mean.

To aim the same journey at a real server later, set the flow's Target base URL. Only load-test systems you own or have permission to test.

You can do the same from ApiWorkbench: open the collection's ⋯ menu and choose Load test. See Load testing in ApiWorkbench.

What you learned ​

  • Capture a token at sign-in and send it as a Bearer token.
  • A request without the token is itself a test.
  • In conditional rules, order decides which response wins.
  • A data file runs one request with many inputs, including the edges.
  • A flow runs a whole journey with many users at once.

Next steps ​