SuperTest Cheatsheet¶
Instalación¶
| Platform | Command |
|---|---|
| npm (All Platforms) | INLINE_CODE_20 |
| Yarn (All Platforms) | INLINE_CODE_21 |
| With Jest | INLINE_CODE_22 |
| With Mocha | INLINE_CODE_23 |
| With TypeScript | INLINE_CODE_24 |
| Specific Version | INLINE_CODE_25 |
Basic HTTP Métodos¶
| Command | Description |
|---|---|
| INLINE_CODE_26 | Send GET request to endpoint |
| INLINE_CODE_27 | Send POST request to endpoint |
| INLINE_CODE_28 | Send PUT request to update resource |
| INLINE_CODE_29 | Send PATCH request for partial update |
| INLINE_CODE_30 | Send DELETE request to remove resource |
| INLINE_CODE_31 | Send HEAD request (headers only) |
| INLINE_CODE_32 | Send OPTIONS request for CORS preflight |
| INLINE_CODE_33 | Send JSON data in request body |
| INLINE_CODE_34 | Add query parameters to URL |
| INLINE_CODE_35 | Set request header |
| INLINE_CODE_36 | Assert HTTP status code |
| INLINE_CODE_37 | Assert response header value |
| INLINE_CODE_38 | Execute request with callback |
| INLINE_CODE_39 | Execute request with Promise/async-await |
Asserciones " Expectations¶
| Command | Description |
|---|---|
| INLINE_CODE_40 | Expect exact status code |
| INLINE_CODE_41 | Expect status and exact body match |
| INLINE_CODE_42 | Expect exact header value |
| INLINE_CODE_43 | Expect header matching regex |
| INLINE_CODE_44 | Custom assertion function |
| INLINE_CODE_45 | Expect status and body matching regex |
| INLINE_CODE_46 | Expect redirect location header |
| INLINE_CODE_47 | Expect exact JSON body match |
Solicitar configuración¶
| Command | Description |
|---|---|
| INLINE_CODE_48 | Set single request header |
| INLINE_CODE_49 | Set multiple headers |
| INLINE_CODE_50 | Set HTTP Basic Authentication |
| INLINE_CODE_51 | Add form field (multipart) |
| INLINE_CODE_52 | Attach file for upload |
| INLINE_CODE_53 | Attach file from buffer |
| INLINE_CODE_54 | Set request timeout in milliseconds |
| INLINE_CODE_55 | Follow up to 5 redirects |
| INLINE_CODE_56 | Set Content-Type header |
| INLINE_CODE_57 | Set Accept header |
| INLINE_CODE_58 | Send raw string body |
| INLINE_CODE_59 | Send binary data |
Advanced Usage¶
| Command | Description |
|---|---|
| INLINE_CODE_60 | Create agent for persistent cookies |
| INLINE_CODE_61 | Use agent for authenticated requests |
| INLINE_CODE_62 | Test external API endpoints |
| INLINE_CODE_63 | Custom response parser |
| INLINE_CODE_64 | Buffer response body |
| INLINE_CODE_65 | Set expected response type |
| INLINE_CODE_66 | Retry failed requests 3 times |
| INLINE_CODE_67 | Set custom CA certificate |
| INLINE_CODE_68 | Set client certificate |
| INLINE_CODE_69 | Set client private key |
| INLINE_CODE_70 | Set PFX/PKCS12 certificate |
| INLINE_CODE_71 | Disable TLS certificate validation |
Testing Patterns¶
| Pattern | Description |
|---|---|
| INLINE_CODE_72 | Store response for multiple assertions |
| INLINE_CODE_73 | Assert on response body with test framework |
| INLINE_CODE_74 | Assert on response headers |
| INLINE_CODE_75 | Alternative status assertion |
| INLINE_CODE_76 | Parallel request testing |
| INLINE_CODE_77 | Sequential test requests |
Configuración¶
Configuración de pruebas básicas¶
// test/setup.js
const request = require('supertest');
const app = require('../app');
module.exports = { request, app };
Configuración 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"
}
}
Environment Variables¶
// 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');
});
});
});
Buenas prácticas¶
-
Use async/await syntax: Más limpio y más legible que callbacks. El JavaScript moderno admite este patrón de forma nativa.
javascript const res = await request(app).get('/api/users').expect(200); -
Install as dev dependency: SuperTest es una herramienta de prueba y sólo debe estar en
devDependencies, no dependencias de producción.bash npm install supertest --save-dev -
No empiece el servidor manualmente: SuperTest maneja la unión del servidor automáticamente. Pase la aplicación Express directamente sin llamar
app.listen()_. ```javascript // Good: Export app without listening module.exports = app;
// Bad: Don't do this in test files app.listen(3000); ```
-
Use request.agent() for session testing: Al probar rutas autenticadas o sesiones basadas en cookies, cree un agente que persista las cookies a través de las solicitudes.
javascript const agent = request.agent(app); await agent.post('/login').send(credentials); await agent.get('/protected'); // Cookies persist -
Cambiar las expectativas para pruebas limpias: Múltiples llamadas
.expect()pueden ser encadenadas para afirmaciones integrales en una sola prueba.javascript await request(app) .get('/api/users') .expect(200) .expect('Content-Type', /json/) .expect((res) => expect(res.body).toHaveLength(10));
Respuestas extremas para afirmaciones complejas: Capturar el objeto de respuesta cuando usted necesita realizar múltiples afirmaciones en diferentes partes.
javascript
const res = await request(app).get('/api/users').expect(200);
expect(res.body).toHaveLength(5);
expect(res.headers['x-total-count']).toBe('100');
Test both success and failure cases: Siempre prueba escenarios de error, fallas de validación y casos de borde junto a caminos felices.
javascript
test('returns 404 for non-existent user', async () => {
await request(app).get('/api/users/99999').expect(404);
});
-
Usar nombres de prueba descriptivos: Escribir descripciones de pruebas que explican claramente qué comportamiento se está verificando.
javascript test('POST /api/users returns 400 when email is missing', async () => { // Test implementation }); -
Clean up test data: Use
beforeEach____afterEachganchos para restablecer el estado de la base de datos y garantizar el aislamiento de la prueba.javascript afterEach(async () => { await User.deleteMany({}); }); -
Separar los plazos adecuados: Para puntos finales lentos o llamadas externas de API, configure los valores de timeout para evitar fallos falsos.
javascript await request(app).get('/api/slow').timeout(10000).expect(200);
Troubleshooting¶
__TABLE_121_ No se puede probar API externas ← SuperTest funciona con URL externas: request('https://api.example.com').get('/endpoint'). Asegurar el acceso a la red y la disponibilidad de API. Silencio