Course contentsShow
← Node.js
Lesson 1570 of 1,98014. Testing Methodologies and Quality AssuranceFree lesson

Mocking Global Configuration Objects

Safely manipulate runtime settings for testing without affecting the entire process.

In this lesson, you will learn how to safely intercept and override global configuration objects during test execution to ensure your test suite remains deterministic without polluting the environment.

The Challenge of Global State

In large-scale Node.js applications, configuration objects (like config.json or process.env) are often loaded once at application startup. Because these objects are typically globally scoped, modifying them in one test file can cause side effects that cascade into unrelated tests, leading to "flaky" suites where the order of execution determines success or failure.

Isolation via Proxying and Restoration

To safely manipulate these settings, you must employ a pattern of "Capture, Patch, and Restore." Rather than directly mutating the original object, you should use your testing framework to temporarily override the values and strictly revert them in an afterEach or afterAll hook.

Consider a global appConfig object:

// config.js
export const appConfig = {
  featureFlags: { betaUI: false },
  timeout: 5000
};

// test.js
import { appConfig } from './config.js';

describe('Beta UI Tests', () => {
  let originalConfig;

  beforeEach(() => {
    // 1. Capture original state
    originalConfig = { ...appConfig };
  });

  afterEach(() => {
    // 2. Restore exact original state
    Object.assign(appConfig, originalConfig);
  });

  it('enables the beta interface', () => {
    appConfig.featureFlags.betaUI = true;
    // Perform test logic...
    expect(appConfig.featureFlags.betaUI).toBe(true);
  });
});

Best Practices for Stability

  1. Shallow vs. Deep Copies: If your configuration object contains nested objects, ensure you are creating a deep copy during the "Capture" phase so that modifications to nested properties don't persist after the afterEach hook runs.
  2. Read-Only Enforcements: If you have the luxury of refactoring, move away from mutable global objects. Instead, use a dependency injection pattern where the configuration is passed into the constructors of your services.
  3. Environment Variable Alternatives: For process.env, treat it as an immutable source of truth; use specialized tools like jest.spyOn(process, 'env', 'get') or dedicated configuration loaders that allow for runtime injection overrides without touching the actual shell process.

Key Takeaway: Always pair a configuration override with a guaranteed restoration hook to prevent cross-test contamination and ensure your global environment resets to a pristine state after every execution.