Log collection, monitoring, and assertion utilities for testing log output with pattern matching and multi-logger support.
Start collecting logger messages for testing and verification purposes.
/**
* Start collecting logger messages for testing
* @param {string|Logger} [logger] - Logger instance or name (defaults to app.logger)
*/
app.mockLog(logger);
/**
* Collection logger message in cluster mode
* @param {string} [logger] - Logger name (defaults to 'logger')
*/
clusterApp.mockLog(logger);Usage Examples:
// Basic log collection
describe('logging tests', () => {
let app;
beforeEach(() => {
app = mm.app();
return app.ready();
});
afterEach(() => app.close());
it('should collect default logger messages', async () => {
app.mockLog(); // Start collecting app.logger messages
// Trigger some logging
await app.httpRequest()
.get('/api/test')
.expect(200);
app.expectLog('Request processed successfully');
});
// Named logger collection
it('should collect specific logger messages', async () => {
app.mockLog('accessLogger'); // Collect specific logger
await app.httpRequest()
.get('/api/users')
.expect(200);
app.expectLog('GET /api/users', 'accessLogger');
});
});Assert the presence or absence of specific log messages and patterns.
/**
* Assert that a string/pattern exists in logs
* @param {string|RegExp} str - String or pattern to find
* @param {string|Logger} [logger] - Logger instance or name
*/
app.expectLog(str, logger);
/**
* Assert that a string/pattern does not exist in logs
* @param {string|RegExp} str - String or pattern that should not be found
* @param {string|Logger} [logger] - Logger instance or name
*/
app.notExpectLog(str, logger);
/**
* Cluster mode log assertions (string-only)
* @param {string} str - String to find in logs
* @param {string} [logger] - Logger name
*/
clusterApp.expectLog(str, logger);
clusterApp.notExpectLog(str, logger);Usage Examples:
// String matching
it('should log user creation', async () => {
app.mockLog();
await app.httpRequest()
.post('/api/users')
.send({ name: 'Alice' })
.expect(201);
app.expectLog('User created: Alice');
app.notExpectLog('Error creating user');
});
// RegExp pattern matching
it('should log request timing', async () => {
app.mockLog();
await app.httpRequest()
.get('/api/slow-endpoint')
.expect(200);
app.expectLog(/Request completed in \d+ms/);
app.notExpectLog(/Error:/);
});
// Multiple logger testing
it('should log to different loggers', async () => {
app.mockLog('app');
app.mockLog('access');
app.mockLog('error');
await app.httpRequest()
.post('/api/invalid')
.send({ invalid: 'data' })
.expect(400);
app.expectLog('Validation failed', 'app');
app.expectLog('POST /api/invalid 400', 'access');
app.expectLog('Invalid request data', 'error');
});Test custom loggers and logger configurations.
Usage Examples:
// Custom logger instance
it('should use custom logger', async () => {
const customLogger = app.getLogger('custom');
app.mockLog(customLogger);
// Code that uses custom logger
customLogger.info('Custom operation started');
customLogger.info('Custom operation completed');
app.expectLog('Custom operation started', customLogger);
app.expectLog('Custom operation completed', customLogger);
});
// Logger with different levels
it('should capture different log levels', async () => {
app.mockLog();
app.logger.debug('Debug message');
app.logger.info('Info message');
app.logger.warn('Warning message');
app.logger.error('Error message');
app.expectLog('Debug message');
app.expectLog('Info message');
app.expectLog('Warning message');
app.expectLog('Error message');
});
// Conditional logging based on environment
it('should log based on environment', async () => {
app.mockEnv('development');
app.mockLog();
// Code that logs differently in development
if (app.config.env === 'development') {
app.logger.debug('Development debug info');
}
app.expectLog('Development debug info');
});Specifically test error logging and exception handling.
Usage Examples:
// Exception logging
it('should log exceptions', async () => {
app.mockLog();
app.mockServiceError('user', 'find', new Error('Database connection failed'));
await app.httpRequest()
.get('/api/users/123')
.expect(500);
app.expectLog('Database connection failed');
app.expectLog(/Error in user\.find/);
});
// Custom error logging
it('should log validation errors', async () => {
app.mockLog();
await app.httpRequest()
.post('/api/users')
.send({ email: 'invalid-email' })
.expect(400);
app.expectLog('Validation error');
app.expectLog('Invalid email format');
app.notExpectLog('User created successfully');
});
// Stack trace logging
it('should include stack traces in error logs', async () => {
app.mockLog();
const error = new Error('Test error');
app.mockServiceError('test', 'method', error);
try {
await app.service.test.method();
} catch (e) {
// Error should be logged with stack trace
}
app.expectLog('Test error');
app.expectLog(/at.*test.*method/); // Stack trace pattern
});Test performance-related logging and request timing.
Usage Examples:
// Request timing logs
it('should log request timing', async () => {
app.mockLog();
await app.httpRequest()
.get('/api/data')
.expect(200);
app.expectLog(/GET \/api\/data.*\d+ms/);
});
// Slow request warnings
it('should warn about slow requests', async () => {
app.mockLog();
// Mock slow service
app.mockService('data', 'fetch', async () => {
await new Promise(resolve => setTimeout(resolve, 1000));
return { data: 'slow response' };
});
await app.httpRequest()
.get('/api/slow')
.expect(200);
app.expectLog(/Slow request detected.*1\d{3}ms/);
});
// Database query timing
it('should log database query performance', async () => {
app.mockLog('sqlLogger');
await app.httpRequest()
.get('/api/users')
.expect(200);
app.expectLog(/SELECT.*FROM users.*\d+ms/, 'sqlLogger');
});Test structured logging with JSON objects and metadata.
Usage Examples:
// JSON log entries
it('should log structured data', async () => {
app.mockLog();
app.logger.info('User action', {
userId: 123,
action: 'login',
ip: '192.168.1.1',
userAgent: 'test-client'
});
app.expectLog('User action');
app.expectLog(/"userId":123/);
app.expectLog(/"action":"login"/);
});
// Log metadata verification
it('should include request metadata in logs', async () => {
app.mockLog();
await app.httpRequest()
.get('/api/users')
.set('x-request-id', 'req-123')
.expect(200);
app.expectLog(/"requestId":"req-123"/);
app.expectLog(/"method":"GET"/);
app.expectLog(/"url":"\/api\/users"/);
});Test logging to files and file-based log assertions.
Usage Examples:
// File-based log testing (when not using mockLog)
it('should write to log file', async () => {
// Don't call mockLog to test file-based logging
await app.httpRequest()
.get('/api/test')
.expect(200);
// expectLog will read from file when no mockLog was called
app.expectLog('Request completed');
});
// Multiple log files
it('should write to different log files', async () => {
await app.httpRequest()
.post('/api/error-prone')
.send({ invalid: 'data' })
.expect(400);
// Check application log
app.expectLog('Validation failed', 'app');
// Check error log
app.expectLog('Request failed', 'errorLogger');
});Specific logging tests for cluster applications.
Usage Examples:
// Cluster application logging
describe('Cluster logging', () => {
let app;
before(function(done) {
app = mm.cluster({ baseDir: 'test/fixtures/apps/demo' });
app.ready(done);
});
after(function() {
return app.close();
});
it('should log in cluster mode', () => {
app.mockLog(); // Cluster mode
return app.httpRequest()
.get('/api/cluster-test')
.expect(200)
.then(() => {
app.expectLog('Cluster request processed');
});
});
it('should log worker information', () => {
app.mockLog();
return app.httpRequest()
.get('/api/worker-info')
.expect(200)
.then(() => {
app.expectLog(/Worker PID: \d+/);
});
});
});