SuperTest Cheatsheet
Installazione¶
Tabella_115
Basic HTTP Metodi¶
Tabella_116_
Asserzioni e aspettative¶
Tabella_117_
Richiesta configurazione¶
Tabella_118
Uso avanzato¶
Tabella_119_
Testing Patterns¶
Tabella_120
Configurazione¶
Set di test di base¶
// test/setup.js
const request = require('supertest');
const app = require('../app');
module.exports = { request, app };
Configurazione Jest¶
// jest.config.js
module.exports = {
testEnvironment: 'node',
testMatch: ['**/__tests__/**/*.test.js'],
collectCoverageFrom: ['src/**/*.js'],
coveragePathIgnorePatterns: ['/node_modules/']
};
Mocha Configuration¶
Package.json Scripts¶
{
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"test:api": "jest --testPathPattern=api"
}
}
Variabili ambientali¶
// config/test.js
module.exports = {
port: process.env.TEST_PORT || 3001,
database: process.env.TEST_DB || 'test_db',
apiTimeout: process.env.API_TIMEOUT || 5000
};
Common Use Cases¶
Use Case 1: Testing REST API CRUD Operations¶
const request = require('supertest');
const app = require('../app');
describe('User API', () => {
let userId;
// Create
test('POST /api/users - create user', async () => {
const res = await request(app)
.post('/api/users')
.send({ name: 'John Doe', email: 'john@example.com' })
.expect(201)
.expect('Content-Type', /json/);
userId = res.body.id;
expect(res.body.name).toBe('John Doe');
});
// Read
test('GET /api/users/:id - get user', async () => {
await request(app)
.get(`/api/users/${userId}`)
.expect(200)
.expect((res) => {
expect(res.body.name).toBe('John Doe');
});
});
// Update
test('PUT /api/users/:id - update user', async () => {
await request(app)
.put(`/api/users/${userId}`)
.send({ name: 'Jane Doe' })
.expect(200);
});
// Delete
test('DELETE /api/users/:id - delete user', async () => {
await request(app)
.delete(`/api/users/${userId}`)
.expect(204);
});
});
Use Case 2: Testing Authentication Flow¶
const request = require('supertest');
const app = require('../app');
describe('Authentication', () => {
let authToken;
test('POST /auth/register - register new user', async () => {
await request(app)
.post('/auth/register')
.send({
email: 'test@example.com',
password: 'SecurePass123!',
name: 'Test User'
})
.expect(201);
});
test('POST /auth/login - login user', async () => {
const res = await request(app)
.post('/auth/login')
.send({
email: 'test@example.com',
password: 'SecurePass123!'
})
.expect(200)
.expect('Content-Type', /json/);
authToken = res.body.token;
expect(authToken).toBeDefined();
});
test('GET /api/profile - access protected route', async () => {
await request(app)
.get('/api/profile')
.set('Authorization', `Bearer ${authToken}`)
.expect(200)
.expect((res) => {
expect(res.body.email).toBe('test@example.com');
});
});
test('GET /api/profile - reject without token', async () => {
await request(app)
.get('/api/profile')
.expect(401);
});
});
Use Case 3: Testing File Upload¶
const request = require('supertest');
const app = require('../app');
const path = require('path');
describe('File Upload', () => {
test('POST /api/upload - upload single file', async () => {
const filePath = path.join(__dirname, 'fixtures', 'test.pdf');
const res = await request(app)
.post('/api/upload')
.attach('document', filePath)
.field('title', 'Test Document')
.field('description', 'A test file upload')
.expect(200)
.expect('Content-Type', /json/);
expect(res.body.filename).toMatch(/\.pdf$/);
expect(res.body.size).toBeGreaterThan(0);
});
test('POST /api/upload - upload multiple files', async () => {
await request(app)
.post('/api/upload/multiple')
.attach('files', 'test/fixtures/file1.pdf')
.attach('files', 'test/fixtures/file2.pdf')
.expect(200)
.expect((res) => {
expect(res.body.files).toHaveLength(2);
});
});
});
Use Case 4: Testing with Persistent Sessions¶
const request = require('supertest');
const app = require('../app');
describe('Session Management', () => {
const agent = request.agent(app);
test('Login and maintain session', async () => {
// Login
await agent
.post('/auth/login')
.send({ username: 'user', password: 'pass' })
.expect(200);
// Session persists - can access protected route
await agent
.get('/api/dashboard')
.expect(200);
// Session still valid for subsequent requests
await agent
.get('/api/profile')
.expect(200);
// Logout
await agent
.post('/auth/logout')
.expect(200);
// Session expired - access denied
await agent
.get('/api/dashboard')
.expect(401);
});
});
Use Case 5: Testing Error Handling¶
const request = require('supertest');
const app = require('../app');
describe('Error Handling', () => {
test('404 - Resource not found', async () => {
await request(app)
.get('/api/users/99999')
.expect(404)
.expect((res) => {
expect(res.body.error).toBe('User not found');
expect(res.body.code).toBe('USER_NOT_FOUND');
});
});
test('400 - Validation error', async () => {
await request(app)
.post('/api/users')
.send({ name: '' }) // Invalid data
.expect(400)
.expect((res) => {
expect(res.body.errors).toBeDefined();
expect(res.body.errors.name).toContain('required');
});
});
test('429 - Rate limit exceeded', async () => {
// Make multiple requests to trigger rate limit
const requests = Array(101).fill().map(() =>
request(app).get('/api/users')
);
const responses = await Promise.all(requests);
const rateLimited = responses.find(r => r.status === 429);
expect(rateLimited).toBeDefined();
expect(rateLimited.body.error).toMatch(/rate limit/i);
});
test('500 - Internal server error', async () => {
await request(app)
.get('/api/trigger-error')
.expect(500)
.expect((res) => {
expect(res.body.error).toBe('Internal server error');
});
});
});
Migliori Pratiche¶
-
Utilizza la sintassi asinc/await: Più pulita e più leggibile delle chiamate. Modern JavaScript supporta questo modello in modo nativo. Traduzione:
-
Install as dev dipendenza # SuperTest è uno strumento di prova e dovrebbe essere solo in
devDependencies, non dipendenze di produzione.¶Traduzione:
-
** Non avviare il server manualmente**: SuperTest gestisce automaticamente il binding del server. Passare l'applicazione Express direttamente senza chiamare
app.listen().
¶
-
** Utilizzare request.agent() per i test di sessione**: Quando si verificano percorsi autenticati o sessioni basate sui cookie, creare un agente per persistere dei cookie attraverso le richieste. Traduzione:
-
**Cambiare le aspettative per i test più puliti ** Più chiamate
.expect()_ possono essere incatenate per affermazioni complete in un unico test. Traduzione: -
Rispondenze di vendita per affermazioni complesse: Cattura l'oggetto di risposta quando è necessario eseguire più affermazioni su parti diverse. Traduzione:
-
**I casi di successo e di fallimento ** Testare sempre scenari di errore, guasti di validazione e casi di bordo accanto a percorsi felici. Traduzione:
-
Utilizzare i nomi dei test descrittivi: Scrivere descrizioni dei test che spiegano chiaramente che comportamento viene verificato. Traduzione:
-
Clean up test data*: Utilizzare
beforeEach/_INLINE_CODE_82__ per ripristinare lo stato del database e garantire l'isolamento del test. Traduzione: -
Set timeouts appropriati**: Per gli endpoint lenti o le chiamate API esterne, configurare i valori di timeout per evitare errori falsi. Traduzione:
Risoluzione dei problemi¶
TABLE_121_| Non è possibile testare le API esterne | SuperTest funziona con URL esterni: request('https://api.example.com').get('/endpoint'). Assicurare l'accesso alla rete e la disponibilità API. #