or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

application-creation.mdcontext-session-mocking.mdenvironment-configuration.mdhttp-client-mocking.mdhttp-testing-utilities.mdindex.mdlogging-assertions.mdmock-restoration.mdservice-mocking.md
tile.json

mock-restoration.mddocs/

Mock Restoration

Comprehensive mock cleanup and restoration utilities for maintaining test isolation and preventing test interference.

Capabilities

Global Mock Restoration

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);
  });
});

Application Mock Restoration

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');
  });
});

HTTP Agent Restoration

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');
    }
  });
});

Cluster Mock Restoration

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);
      });
  });
});

Selective Mock Restoration

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();
  });
});

Restoration Error Handling

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);
  });
});

Restoration Best Practices

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
    });
  });
});

Automatic Restoration with Hooks

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();
});