如何在NodeJS/Mocha/Chai中对路由函数做单元测试及实操疑问
Hey there! Let's break down how to execute your route functions with parameters for unit testing, since you already have Chai set up in your project/test folder. I'll cover two common approaches depending on your setup:
1. Simulate HTTP Requests with Supertest (Recommended for Frameworks like Express)
This is the most straightforward way if you're using a web framework like Express, because it mimics real HTTP calls and handles middleware (like body parsers) automatically.
First, if you haven't already, install Supertest as a dev dependency:
npm install supertest --save-dev
Then, in your test file, import your app instance, Supertest, and Chai's assertions. Here are examples for different parameter types:
Path Parameters (e.g., /users/:id)
const request = require('supertest'); const { expect } = require('chai'); const app = require('../app'); // Path to your Express app entry describe('User Routes', () => { it('should fetch a user by their ID', async () => { const testUserId = 456; const response = await request(app).get(`/users/${testUserId}`); expect(response.status).to.equal(200); expect(response.body.id).to.equal(testUserId); // Add more Chai assertions for your route's expected response }); });
Query Parameters (e.g., /search?name=John)
it('should return users matching a search query', async () => { const searchName = 'John'; const response = await request(app) .get('/users/search') .query({ name: searchName }); // Pass query params here expect(response.status).to.equal(200); expect(response.body).to.be.an('array').that.satisfies(users => users.some(user => user.name === searchName) ); });
Request Body Parameters (e.g., POST /users)
it('should create a new user with provided body data', async () => { const newUserPayload = { name: 'Jane Doe', email: 'jane@example.com' }; const response = await request(app) .post('/users') .send(newUserPayload); // Send body params as JSON expect(response.status).to.equal(201); expect(response.body.name).to.equal(newUserPayload.name); });
2. Directly Call Route Handler Functions (Manual req/res Mocking)
If you want to test the route logic in isolation (without spinning up the entire app), you can manually mock the req and res objects that get passed to your route handler.
Suppose your route handler looks like this:
// routes/users.js exports.getUserById = (req, res) => { const userId = req.params.id; // Your business logic here res.status(200).json({ id: userId, name: 'John Doe' }); };
Here's how to test it directly with Chai:
const { expect } = require('chai'); const { getUserById } = require('../routes/users'); describe('getUserById Route Handler', () => { it('should respond with the correct user ID', (done) => { // Mock the req object with your parameter const mockReq = { params: { id: '789' } }; // Mock the res object to track status and JSON responses const mockRes = { status: (statusCode) => { expect(statusCode).to.equal(200); return mockRes; // Allow chaining (like res.status().json()) }, json: (responseData) => { expect(responseData.id).to.equal('789'); done(); // Signal to Mocha that the test is complete } }; // Execute the route handler with your mocked objects getUserById(mockReq, mockRes); }); });
Quick Notes:
- If your routes rely on middleware (like
express.json()for parsing request bodies), Supertest will handle this automatically since it uses your full app instance. - When manually mocking
req, make sure to include all properties your route needs (e.g.,req.query,req.body,req.headers) based on its logic. - You can use libraries like Sinon to simplify mocking
req/resif you don't want to build mocks from scratch, but manual mocking works fine for simple cases.
内容的提问来源于stack exchange,提问作者Bartłomiej Flis

