Mock testing library for Egg.js applications with comprehensive mocking capabilities for HTTP, services, contexts, and testing utilities
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Supertest integration and enhanced testing utilities for making HTTP requests with custom assertion methods and comprehensive test coverage.
Create supertest-compatible request instances for testing HTTP endpoints.
/**
* Create supertest request instance
* @returns {SupertestRequest} HTTP testing object with methods for all HTTP verbs
*/
app.httpRequest();
interface SupertestRequest {
/** Make GET request */
get(url: string): EggTest;
/** Make POST request */
post(url: string): EggTest;
/** Make PUT request */
put(url: string): EggTest;
/** Make DELETE request */
delete(url: string): EggTest;
/** Make PATCH request */
patch(url: string): EggTest;
/** Make HEAD request */
head(url: string): EggTest;
/** Make OPTIONS request */
options(url: string): EggTest;
/** Make TRACE request */
trace(url: string): EggTest;
/** Make CONNECT request */
connect(url: string): EggTest;
}
type Methods = 'get' | 'post' | 'delete' | 'del' | 'put' | 'head' | 'options' | 'patch' | 'trace' | 'connect';Usage Examples:
// Basic HTTP testing
describe('API endpoints', () => {
let app;
before(() => {
app = mm.app();
return app.ready();
});
after(() => app.close());
it('should GET /', () => {
return app.httpRequest()
.get('/')
.expect(200)
.expect('Content-Type', /html/);
});
it('should POST /api/users', () => {
return app.httpRequest()
.post('/api/users')
.send({ name: 'Alice', email: 'alice@example.com' })
.expect(201)
.expect('Content-Type', /json/)
.expect(res => {
assert(res.body.id);
assert.equal(res.body.name, 'Alice');
});
});
});Extended supertest interface with additional assertion methods specific to Egg.js testing.
interface EggTest extends Test {
/**
* Assert that response does not contain specified header
* @param {string} name - Header name to check for absence
* @param {Function} [callback] - Optional callback function
* @returns {EggTest} Test instance for chaining
*/
unexpectHeader(name: string, callback?: Function): EggTest;
/**
* Assert that response contains specified header
* @param {string} name - Header name to check for presence
* @param {Function} [callback] - Optional callback function
* @returns {EggTest} Test instance for chaining
*/
expectHeader(name: string, callback?: Function): EggTest;
}Usage Examples:
// Header presence testing
it('should have security headers', () => {
return app.httpRequest()
.get('/secure')
.expect(200)
.expectHeader('x-frame-options')
.expectHeader('x-content-type-options')
.unexpectHeader('x-powered-by');
});
// Header value testing
it('should set correct content type', () => {
return app.httpRequest()
.get('/api/data')
.expect(200)
.expectHeader('content-type', /application\/json/)
.unexpectHeader('set-cookie');
});
// Custom header assertions
it('should have rate limit headers', () => {
return app.httpRequest()
.get('/api/limited')
.expect(200)
.expectHeader('x-ratelimit-limit')
.expectHeader('x-ratelimit-remaining')
.expect(res => {
const limit = parseInt(res.headers['x-ratelimit-limit']);
const remaining = parseInt(res.headers['x-ratelimit-remaining']);
assert(limit > 0);
assert(remaining >= 0);
assert(remaining <= limit);
});
});Send various types of request data and test request handling.
Usage Examples:
// JSON request body
it('should handle JSON data', () => {
return app.httpRequest()
.post('/api/data')
.send({
name: 'Test Item',
value: 123,
active: true
})
.expect(201)
.expect('Content-Type', /json/)
.expect(res => {
assert.equal(res.body.name, 'Test Item');
assert.equal(res.body.value, 123);
});
});
// Form data
it('should handle form data', () => {
return app.httpRequest()
.post('/submit')
.type('form')
.send({ username: 'alice', password: 'secret' })
.expect(302)
.expect('Location', '/dashboard');
});
// File upload simulation
it('should handle file upload', () => {
return app.httpRequest()
.post('/upload')
.attach('file', Buffer.from('file content'), 'test.txt')
.field('description', 'Test file')
.expect(200)
.expect(res => {
assert.equal(res.body.filename, 'test.txt');
assert.equal(res.body.size, 12);
});
});
// Query parameters
it('should handle query parameters', () => {
return app.httpRequest()
.get('/search')
.query({ q: 'test', limit: 10, offset: 0 })
.expect(200)
.expect(res => {
assert.equal(res.body.query, 'test');
assert.equal(res.body.results.length, 10);
});
});Test various authentication mechanisms and protected endpoints.
Usage Examples:
// Bearer token authentication
it('should require authentication', () => {
return app.httpRequest()
.get('/api/protected')
.expect(401);
});
it('should accept valid token', () => {
return app.httpRequest()
.get('/api/protected')
.set('Authorization', 'Bearer valid-token')
.expect(200)
.expect(res => {
assert(res.body.user);
assert.equal(res.body.user.authenticated, true);
});
});
// Basic authentication
it('should handle basic auth', () => {
return app.httpRequest()
.get('/api/basic')
.auth('username', 'password')
.expect(200);
});
// Session-based authentication
it('should handle session auth', () => {
return app.httpRequest()
.post('/login')
.send({ username: 'alice', password: 'secret' })
.expect(302)
.then(res => {
const cookies = res.headers['set-cookie'];
return app.httpRequest()
.get('/dashboard')
.set('Cookie', cookies)
.expect(200);
});
});
// CSRF token testing
it('should handle CSRF protection', () => {
// Get CSRF token
return app.httpRequest()
.get('/form')
.expect(200)
.then(res => {
const token = res.body.csrfToken;
// Use token in POST request
return app.httpRequest()
.post('/api/action')
.send({ data: 'test', _csrf: token })
.expect(200);
});
});Test error handling and error response formats.
Usage Examples:
// Test error status codes
it('should return 404 for missing resource', () => {
return app.httpRequest()
.get('/api/users/nonexistent')
.expect(404)
.expect('Content-Type', /json/)
.expect(res => {
assert.equal(res.body.error, 'User not found');
});
});
// Test validation errors
it('should validate required fields', () => {
return app.httpRequest()
.post('/api/users')
.send({ email: 'invalid-email' })
.expect(400)
.expect(res => {
assert(res.body.errors);
assert(res.body.errors.name);
assert(res.body.errors.email);
});
});
// Test server errors
it('should handle server errors gracefully', () => {
// Mock service to throw error
app.mockServiceError('user', 'create', 'Database connection failed');
return app.httpRequest()
.post('/api/users')
.send({ name: 'Alice', email: 'alice@example.com' })
.expect(500)
.expect(res => {
assert.equal(res.body.error, 'Internal server error');
});
});Test different content types and response formats.
Usage Examples:
// JSON API testing
it('should return JSON', () => {
return app.httpRequest()
.get('/api/data')
.expect(200)
.expect('Content-Type', /application\/json/)
.expect(res => {
assert(typeof res.body === 'object');
});
});
// XML response testing
it('should return XML', () => {
return app.httpRequest()
.get('/api/data.xml')
.expect(200)
.expect('Content-Type', /application\/xml/)
.expect(res => {
assert(typeof res.text === 'string');
assert(res.text.includes('<?xml'));
});
});
// Plain text response
it('should return plain text', () => {
return app.httpRequest()
.get('/health')
.expect(200)
.expect('Content-Type', /text\/plain/)
.expect('OK');
});
// HTML response
it('should return HTML', () => {
return app.httpRequest()
.get('/')
.expect(200)
.expect('Content-Type', /text\/html/)
.expect(res => {
assert(res.text.includes('<html>'));
});
});HTTP testing specifically for cluster applications with supertest compatibility.
/**
* Create supertest request for cluster testing
* @returns {SupertestRequest} HTTP testing object for cluster
*/
clusterApp.httpRequest();Usage Examples:
// Cluster application testing
describe('ClusterApplication HTTP', () => {
let app;
before(function(done) {
app = mm.cluster({ baseDir: 'test/fixtures/apps/demo' });
app.ready(done);
});
after(function() {
return app.close();
});
it('should handle requests in cluster mode', () => {
return app.httpRequest()
.get('/api/cluster-info')
.expect(200)
.expect(res => {
assert(res.body.pid);
assert(res.body.workers);
});
});
it('should handle concurrent requests', async () => {
const requests = Array.from({ length: 10 }, (_, i) =>
app.httpRequest()
.get(`/api/data/${i}`)
.expect(200)
);
const responses = await Promise.all(requests);
responses.forEach((res, i) => {
assert.equal(res.body.id, i);
});
});
});Create custom assertion helpers for common testing patterns.
Usage Examples:
// Custom helper for API responses
function expectApiSuccess(test) {
return test
.expect(200)
.expect('Content-Type', /json/)
.expect(res => {
assert.equal(res.body.success, true);
assert(res.body.data);
});
}
// Usage
it('should return successful API response', () => {
return expectApiSuccess(
app.httpRequest().get('/api/success')
);
});
// Custom helper for paginated responses
function expectPaginatedResponse(test, expectedPage = 1) {
return test
.expect(200)
.expect(res => {
assert(res.body.data);
assert(Array.isArray(res.body.data));
assert.equal(res.body.page, expectedPage);
assert(typeof res.body.total === 'number');
});
}
// Usage
it('should return paginated users', () => {
return expectPaginatedResponse(
app.httpRequest().get('/api/users?page=2'),
2
);
});Install with Tessl CLI
npx tessl i tessl/npm-egg-mock