babel-plugin-mockable-imports

raw JSON →
2.0.1 verified Sat Apr 25 auth: no javascript

A Babel plugin that transforms JavaScript/TypeScript modules to enable mocking of ES imports in tests. Current stable version is 2.0.1. It works with any test runner, bundler, and environment (Node or browser). Unlike tools like proxyquire or rewire, it operates at the Babel AST level, making it compatible with modern ES module syntax. The plugin detects incorrect usage (e.g., mocking non-existent imports) and is designed to minimize runtime overhead. It supports both JavaScript and TypeScript, and can be selectively enabled via Babel's env configuration.

error $imports is not defined
cause The module has not been transformed by the plugin, or the plugin is not applied.
fix
Verify the plugin is enabled in your Babel config and that the module is being processed. Check if the module is excluded via exclude or include patterns.
error Cannot find module 'babel-plugin-mockable-imports'
cause The plugin is not installed or not in the correct Babel plugins directory.
fix
Run npm install --save-dev babel-plugin-mockable-imports and ensure your Babel config file is in the project root.
error Error: Plugin "mockable-imports" could not be loaded from "@babel/core".
cause Incompatible version of @babel/core or missing peer dependency.
fix
Ensure @babel/core is installed: npm install --save-dev @babel/core. Check that the version matches the plugin requirements.
error Uncaught TypeError: $imports.$mock is not a function
cause The $imports object exists but is not the expected one (e.g., imported from a module that does not use the plugin).
fix
Import $imports from the specific module under test, not from a shared module. Check that the module is transformed.
breaking v2.0.0 converted the plugin and its runtime helpers to ES modules. If you use CommonJS-based tooling (e.g., older Node versions, or require() in Babel config), the plugin will not work. You must ensure your environment supports ESM, or use v1.x.
fix Switch to Node >=12.17 or use ESM-compatible tooling. For backward compatibility, stick with v1.x.
gotcha This plugin should only be applied in test or development builds. Applying it in production will cause performance overhead and leak the $imports object.
fix Use Babel's env configuration or conditional builds to only include the plugin for test/development environments.
gotcha The $imports object is exported from transformed modules. If you import from a module that hasn't been transformed (e.g., node_modules), $imports will not exist and importing it will cause a runtime error.
fix Ensure the plugin is applied to all modules you want to mock. Use include/exclude options in Babel config.
deprecated In v1.8.0, excludeImportsFromModules was updated to support regex patterns. The previous string-only patterns may not work as expected.
fix If you use excludeImportsFromModules, provide a RegExp object instead of a string.
gotcha When mocking a module, if you specify an export name that does not exist in the original module, the plugin will report a runtime error. This is by design but can catch developers off-guard.
fix Double-check that the export names you pass to $mock match exactly what the module exports.
npm install babel-plugin-mockable-imports
yarn add babel-plugin-mockable-imports
pnpm add babel-plugin-mockable-imports

Shows installation, Babel config, usage of $imports.$mock and $imports.$restore in a test.

// Install: npm install --save-dev babel-plugin-mockable-imports
// .babelrc
{
  "env": {
    "test": {
      "plugins": ["mockable-imports"]
    }
  }
}

// password.js (module under test)
import {randomBytes} from 'crypto-functions';
export function generatePassword() {
  return randomBytes(10)
    .map(byte => byte.toString(16).padStart(2, '0'))
    .join('');
}

// password.test.js
import {generatePassword, $imports} from './password';

afterEach(() => {
  $imports.$restore();
});

it('generates expected password', () => {
  const fakeRandomBytes = length => Array(length).fill(42);
  $imports.$mock({
    'crypto-functions': {
      randomBytes: fakeRandomBytes,
    },
  });
  expect(generatePassword()).toBe('2a2a2a2a2a2a2a2a2a2a');
});