Socket
Socket
Sign inDemoInstall

@node-loaders/mock

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@node-loaders/mock

Loader that mocks imported/required modules.


Version published
Weekly downloads
682
decreased by-1.59%
Maintainers
1
Weekly downloads
 
Created
Source

@node-loaders/mock

Loader that mocks imported/required modules.

Features

  • ESM support
  • CJS support
  • Mixed CJS/ESM support
  • Framework agnostic
  • Typescript support (using a typescript loader, except CJS)
  • Delegates the actual module import to the chain, keeping compatibility with others loaders (like typescript)
  • No cache manipulation is necessary, no drawbacks like why-is-proxyquire-messing-with-my-require-cache
  • Compatible with Typescript's esModuleInterop
  • Full or partial mock support
  • Unused mock detection
  • Configurable mocked module import deep using maxDepth (symbol) property.
  • Trivial to use

Design

Mock uses an unique approach. Importing using mock will create an alternative version of the module using mocked file names. ESM supportes url, mock adds necessary metadata to the url search parameters. CJS uses absolute paths, the metadata is stored and passed using a uuid appended to the file path folowing a .mock extension. The mocked files will continue until maxDepth is reached (-1 by default, deep import).

Prior art: proxyquire, esmock.

Usage

For configuration tools, refer to usage

When using in combination with others @node-loaders modules make sure to use @node-loaders/auto for better interoperability .

Loaders

  • @node-loaders/mock provides esm(import) and commonjs(require) mocking.
  • @node-loaders/mock/esm provides esm(import) mocking only.

ESM

Importing a module with mocked dependencies:

import { importMock, checkMocks } from '@node-loaders/mock';

describe(() => {
  afterAll(() => {
    checkMocks(); // Detects for unused mocks to avoid mistakes on import changes.
  });

  it(async () => {
    const defaultSpy = spy();
    const joinSpy = spy();

    const mockedModule = await importMock('./module.js', {
      '../src/path.js': {
        default: defaultSpy,
        join: joinSpy,
      },
    });

    expect(joinSpy).toBeCalled();
    expect(defaultSpy).toBeCalled();
  });
});

Full mocks:

import { importMock, checkMocks, fullMock } from '@node-loaders/mock';

describe(() => {
  afterAll(() => {
    checkMocks(); // Detects for unused mocks to avoid mistakes on import changes.
  });

  it(async () => {
    const joinSpy = spy();

    const mockedModule = await importMock('./module.js', {
      '../src/path.js': {
        [fullMock]: true, // If a name other than 'join' is imported, a 'Module does not provide an export named' is thrown.
        join: joinSpy,
      },
    });
  });
});

Mock check:

import { importMock, checkMocks, checkMock, ignoreUnused } from '@node-loaders/mock';

describe(() => {
  afterAll(() => {
    checkMocks(); // Detects for unused mocks to avoid mistakes on import changes.
  });

  it(async () => {
    const joinSpy = spy();
    const resolveSpy = spy();

    const mockedModule = await importMock('./module.js', {
      '../src/path.js': {
        join: joinSpy,
      },
      'node:path': {
        [ignoreUnused]: true,
        resolve: resolveSpy,
      },
    });

    checkMock(mockedModule); // throws error if '../src/path.js' was not imported but not on 'node:path'
  });
});

Max depth:

import { importMock, checkMocks, maxDepth } from '@node-loaders/mock';

describe(() => {
  afterAll(() => {
    checkMocks(); // Detects for unused mocks to avoid mistakes on import changes.
  });

  it(async () => {
    const joinSpy = spy();
    const resolveSpy = spy();

    const mockedModule = await importMock('./module.js', {
      '../src/path.js': {
        join: joinSpy, // Mocked when imported from './module.js' file only
      },
      'node:path': {
        [maxDepth]: -1, // Mocked a configurable deep
        resolve: resolveSpy,
      },
    });
  });
});

CommonJS

From an esm module:

import { mockRequire, checkMocks } from '@node-loaders/mock';

describe(() => {
  afterAll(() => {
    checkMocks(); // Detects for unused mocks to avoid mistakes on import changes.
  });

  it(() => {
    const defaultSpy = spy();
    const joinSpy = spy();

    const mockedModule = mockRequire('./module.cjs', {
      '../src/path.cjs': {
        default: defaultSpy,
        join: joinSpy,
      },
    });

    expect(joinSpy).toBeCalled();
    expect(defaultSpy).toBeCalled();
  });
});

From a cjs module:

const { mockRequire } = require('@node-loaders/mock/require');

describe(() => {
  afterAll(() => {
    checkMocks(); // Detects for unused mocks to avoid mistakes on import changes.
  });

  it(() => {
    const defaultSpy = spy();
    const joinSpy = spy();

    const mockedModule = mockRequire('./module.cjs', {
      '../src/path.cjs': {
        default: defaultSpy,
        join: joinSpy,
      },
    });

    expect(joinSpy).toBeCalled();
    expect(defaultSpy).toBeCalled();
  });
});

Known issues

CommonJS (require) mocking doesn't mock typescript modules.

License

MIT

Keywords

FAQs

Package last updated on 16 May 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc