📖 Scenario: You are building a simple Express server that has a GET endpoint to return a list of books. You want to write tests to make sure this endpoint works correctly.
🎯 Goal: Create a basic Express app with a GET endpoint at /books that returns a list of books. Then write a test using a testing library to check that the endpoint returns the correct data and status code.
📋 What You'll Learn
Create an Express app with a GET endpoint /books
The endpoint should return a JSON array of book objects
Write a test that sends a GET request to /books
The test should check that the response status is 200
The test should check that the response body matches the expected books array
💡 Why This Matters
🌍 Real World
Testing GET endpoints is essential for backend APIs to ensure they return the correct data and status codes before deploying to production.
💼 Career
Backend developers and QA engineers often write tests like these to maintain API quality and prevent bugs.
Progress0 / 4 steps
1
Create the books data array
Create a constant array called books with these exact objects: { id: 1, title: '1984' } and { id: 2, title: 'Brave New World' }.
Express
Hint
Use const books = [ ... ] to create the array with two objects inside.
2
Set up the Express app and import modules
Import express and create an app variable called app by calling express().
Express
Hint
Use const express = require('express') and const app = express().
3
Create the GET endpoint for /books
Use app.get with path '/books' and a callback with parameters req and res. Inside the callback, send the books array as JSON using res.json(books).
Express
Hint
Use app.get('/books', (req, res) => { res.json(books); }).
4
Write a test for the GET /books endpoint
Import supertest and use it to create a request object with supertest(app). Write a test named 'GET /books returns books list' that sends a GET request to /books and expects status 200 and the JSON body to equal the books array.
Express
Hint
Use supertest to send a GET request and check status and body with expect.
Practice
(1/5)
1. What is the main purpose of testing GET endpoints in an Express app?
easy
A. To verify the server returns the correct data and status code
B. To check if the server can handle POST requests
C. To test database connection speed
D. To validate CSS styles on the page
Solution
Step 1: Understand GET endpoint testing
Testing GET endpoints means checking if the server responds correctly when a client asks for data.
Step 2: Identify the goal of testing
The goal is to confirm the server sends the right data and proper HTTP status code (like 200 for success).
Final Answer:
To verify the server returns the correct data and status code -> Option A
Quick Check:
Testing GET endpoints = verify data and status [OK]
Hint: GET endpoint tests check response data and status code [OK]
Common Mistakes:
Confusing GET with POST request testing
Testing unrelated features like CSS or database speed
Ignoring status codes in tests
2. Which of the following is the correct way to start a test for a GET endpoint using supertest with Express?
easy
A. app.get('/path').send(200);
B. request(app).get('/path').expect(200, done);
C. supertest.get('/path').expect(200);
D. request.get(app, '/path').expect(200);
Solution
Step 1: Recall supertest syntax
Supertest uses request(app).get('/path') to simulate a GET request to the Express app.
Step 2: Check the correct chaining
Chaining .expect(200, done) checks the status code and signals test completion.
Final Answer:
request(app).get('/path').expect(200, done); -> Option B
Quick Check:
supertest GET syntax = request(app).get(path).expect(status) [OK]
Hint: Use request(app).get(path).expect(status, done) for GET tests [OK]
Common Mistakes:
Calling app.get() instead of request(app).get()
Missing the done callback in async tests
Incorrect method chaining order
3. Given this Express GET endpoint and test code, what will the test output?
The test function is async but does not return or await the request promise, so Jest won't wait for it.
Step 2: Confirm correct fix
Adding return before request(...) or making the test async and awaiting fixes the issue.
Final Answer:
Missing return or await to handle async test -> Option C
Quick Check:
Async test needs return or await [OK]
Hint: Always return or await supertest calls in tests [OK]
Common Mistakes:
Not returning or awaiting async calls in tests
Assuming path or method is wrong without checking
Confusing import errors with test async errors
5. You want to test an Express GET endpoint that returns a list of users, but only those with active status true. Which test code correctly checks this filtering?
app.get('/active-users', (req, res) => {
const users = [
{ id: 1, active: true },
{ id: 2, active: false },
{ id: 3, active: true }
];
res.json(users.filter(u => u.active));
});
// Test code options:
A) await request(app).get('/active-users').expect(200).expect(res => {
if (!res.body.every(u => u.active)) throw new Error('Inactive user found');
});
B) await request(app).get('/active-users').expect(200).expect(res => {
if (res.body.length !== 3) throw new Error('Wrong number of users');
});
C) await request(app).get('/active-users').expect(404);
D) await request(app).get('/active-users').expect(200).expect(res => {
if (!res.body.some(u => u.active === false)) throw new Error('Inactive user found');
});
hard
A. Incorrectly throws error when no inactive users found
B. Incorrectly expects all users, including inactive
C. Wrong status code expectation
D. Checks for inactive users but throws error if found
Solution
Step 1: Understand endpoint filtering
The endpoint returns only users with active: true, so no inactive users should appear.
Step 2: Analyze test options
Checks for inactive users but throws error if found uses every(u => u.active) and throws if any inactive, correctly verifying the filter. Incorrectly expects all users, including inactive expects length !== 3 (wrong, it's 2). Wrong status code expectation expects 404 (wrong). Incorrectly throws error when no inactive users found incorrectly throws error when no inactive users found.
Step 3: Verify A logic
!every(u => u.active) detects any inactive user, matching the requirement.
Final Answer:
Checks for inactive users but throws error if found -> Option D
Quick Check:
Test filters out inactive users = no inactive found [OK]
Hint: Check response has no inactive users with some() or every() [OK]
Common Mistakes:
Expecting all users instead of filtered active only
Using wrong status code in test
Confusing every() and some() logic in tests
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.