Comprehensive mock cleanup and restoration utilities for maintaining test isolation and preventing test interference.
Restore all mocks globally across the entire testing environment.
/**
* Restore all mocks (enhanced version of mm.restore)
* @returns {Promise<void>} Promise that resolves when restoration is complete
*/
async mm.restore();Usage Examples:
// Global restoration in test teardown
describe('API tests', () => {
let app;
beforeEach(() => {
app = mm.app();
return app.ready();
});
afterEach(async () => {
await app.close();
await mm.restore(); // Restore all global mocks
});
it('should mock and restore environment', async () => {
mm.env('production');
mm.consoleLevel('DEBUG');
mm.home('/custom/home');
// Test with mocked environment
assert.equal(process.env.EGG_SERVER_ENV, 'production');
assert.equal(process.env.EGG_LOG, 'DEBUG');
assert.equal(process.env.EGG_HOME, '/custom/home');
// Restoration happens in afterEach
});
it('should have clean environment', async () => {
// Environment should be clean after previous test
assert(!process.env.EGG_MOCK_SERVER_ENV);
assert(!process.env.EGG_LOG);
assert(!process.env.EGG_HOME);
});
});Restore mocks specific to an application instance.
/**
* Restore all application-specific mocks
* @returns {Application} Application instance for chaining
*/
app.mockRestore();Usage Examples:
// Application-level restoration
describe('Service mocking tests', () => {
let app;
beforeEach(() => {
app = mm.app();
return app.ready();
});
afterEach(() => {
app.mockRestore(); // Restore app-level mocks
return app.close();
});
it('should mock and restore services', async () => {
app.mockService('user', 'find', { id: 123, name: 'Alice' });
app.mockSession({ userId: 123 });
app.mockCookies({ theme: 'dark' });
// Use mocked services
const user = await app.service.user.find(123);
assert.equal(user.name, 'Alice');
// Restoration happens in afterEach
});
it('should have clean services', async () => {
// Services should be restored after previous test
const user = await app.service.user.find(123);
// Should call real service, not mock
assert.notEqual(user.name, 'Alice');
});
});Restore mock HTTP agents and urllib interceptors.
/**
* Restore mock HTTP agent
* @returns {Promise<void>} Promise that resolves when agent is restored
*/
async app.mockAgentRestore();Usage Examples:
// HTTP agent restoration
describe('HTTP client tests', () => {
let app;
beforeEach(() => {
app = mm.app();
return app.ready();
});
afterEach(async () => {
await app.mockAgentRestore(); // Restore HTTP agent
await app.close();
});
it('should mock HTTP requests', async () => {
app.mockHttpclient('https://api.example.com/users', {
data: [{ id: 1, name: 'Alice' }]
});
// Make HTTP request through service
const users = await app.service.api.getUsers();
assert.equal(users[0].name, 'Alice');
// Agent restoration happens in afterEach
});
it('should make real HTTP requests', async () => {
// HTTP client should make real requests after restoration
try {
await app.service.api.getUsers();
// This will make a real HTTP request or fail with network error
} catch (error) {
// Expected if no real API available
assert(error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED');
}
});
});Restore mocks in cluster applications.
/**
* Restore cluster application mocks
*/
clusterApp.mockRestore();Usage Examples:
// Cluster restoration
describe('Cluster mock tests', () => {
let app;
before(function(done) {
app = mm.cluster({ baseDir: 'test/fixtures/apps/demo' });
app.ready(done);
});
after(function() {
return app.close();
});
afterEach(() => {
app.mockRestore(); // Restore cluster mocks
});
it('should mock in cluster mode', () => {
// Mock service in cluster
return app.mockService('user', 'find', { id: 123 })
.then(() => app.httpRequest()
.get('/api/user/123')
.expect(200)
.expect(res => {
assert.equal(res.body.id, 123);
})
);
});
it('should have restored cluster mocks', () => {
// Service should be restored in cluster
return app.httpRequest()
.get('/api/user/123')
.expect(res => {
// Should use real service, not mock
assert.notEqual(res.body.id, 123);
});
});
});Restore specific types of mocks while keeping others active.
Usage Examples:
// Selective restoration
describe('Selective restoration tests', () => {
let app;
beforeEach(() => {
app = mm.app();
return app.ready();
});
afterEach(() => {
return app.close();
});
it('should restore only HTTP mocks', async () => {
// Set up multiple mocks
mm.env('test');
app.mockService('user', 'find', { id: 123 });
app.mockHttpclient('https://api.example.com/data', { data: 'mock' });
// Restore only HTTP agent
await app.mockAgentRestore();
// Environment and service mocks should still be active
assert.equal(process.env.EGG_SERVER_ENV, 'test');
const user = await app.service.user.find(123);
assert.equal(user.id, 123);
// HTTP client should be restored
// (would make real request or fail)
// Clean up remaining mocks
app.mockRestore();
await mm.restore();
});
});Handle errors during mock restoration gracefully.
Usage Examples:
// Error handling in restoration
describe('Restoration error handling', () => {
let app;
beforeEach(() => {
app = mm.app();
return app.ready();
});
afterEach(async () => {
try {
await app.mockAgentRestore();
app.mockRestore();
await mm.restore();
} catch (error) {
console.error('Error during cleanup:', error);
// Continue with test cleanup despite errors
}
try {
await app.close();
} catch (error) {
console.error('Error closing app:', error);
}
});
it('should handle restoration errors gracefully', async () => {
// Set up mocks that might cause restoration issues
app.mockHttpclient('https://invalid-url', { data: 'test' });
// Test should pass regardless of restoration errors
const response = await app.httpRequest()
.get('/api/test')
.expect(200);
assert(response.body);
});
});Recommended patterns for mock restoration in different testing scenarios.
Usage Examples:
// Best practice: Global restoration utility
function setupMockRestore() {
afterEach(async () => {
// Always restore in this order for clean teardown
if (global.currentApp) {
await global.currentApp.mockAgentRestore().catch(() => {});
global.currentApp.mockRestore();
await global.currentApp.close();
global.currentApp = null;
}
await mm.restore();
});
}
// Usage across test files
describe('User API tests', () => {
setupMockRestore();
beforeEach(() => {
global.currentApp = mm.app();
return global.currentApp.ready();
});
it('should create user', async () => {
global.currentApp.mockService('user', 'create', { id: 123 });
// Test implementation
});
});
// Best practice: Restoration verification
describe('Mock restoration verification', () => {
it('should fully restore environment', async () => {
// Save original state
const originalEnv = process.env.NODE_ENV;
const originalEggEnv = process.env.EGG_SERVER_ENV;
// Apply mocks
mm.env('production');
mm.consoleLevel('DEBUG');
// Verify mocks are applied
assert.equal(process.env.EGG_SERVER_ENV, 'production');
assert.equal(process.env.EGG_LOG, 'DEBUG');
// Restore
await mm.restore();
// Verify complete restoration
assert.equal(process.env.NODE_ENV, originalEnv);
assert(!process.env.EGG_SERVER_ENV || process.env.EGG_SERVER_ENV === originalEggEnv);
assert(!process.env.EGG_LOG);
assert(!process.env.EGG_HOME);
});
});
// Best practice: Nested restoration
describe('Nested test suites', () => {
// Outer suite restoration
afterEach(async () => {
await mm.restore();
});
describe('Service tests', () => {
let app;
beforeEach(() => {
app = mm.app();
return app.ready();
});
afterEach(() => {
app.mockRestore();
return app.close();
});
it('should handle nested restoration', async () => {
mm.env('test');
app.mockService('test', 'method', 'result');
// Both app.mockRestore() and mm.restore() will be called
// in the correct order due to nested afterEach
});
});
});Set up automatic restoration using test framework hooks.
Usage Examples:
// Mocha hooks for automatic restoration
let globalApp;
// Global hooks
before(() => {
// Global test setup
});
after(async () => {
// Global test teardown
await mm.restore();
});
beforeEach(() => {
globalApp = mm.app();
return globalApp.ready();
});
afterEach(async () => {
if (globalApp) {
await globalApp.mockAgentRestore().catch(() => {});
globalApp.mockRestore();
await globalApp.close();
globalApp = null;
}
});
// Jest hooks for automatic restoration
beforeEach(async () => {
global.testApp = mm.app();
await global.testApp.ready();
});
afterEach(async () => {
if (global.testApp) {
await global.testApp.mockAgentRestore();
global.testApp.mockRestore();
await global.testApp.close();
global.testApp = null;
}
await mm.restore();
});