npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@corez/mocker

v0.23.1

Published

A powerful and flexible TypeScript mocking library for testing

Downloads

19

Readme

@corez/mocker

A powerful TypeScript mocking library with flexible configuration and behavior control.

npm version License TypeScript

Features

  • 🔒 Fully type-safe API with TypeScript
  • 🎭 Function, object and class mocking
  • 🎪 Flexible mock configuration
  • 🎲 Call tracking and verification
  • 💾 Instance isolation and state management
  • 🎯 Getter/Setter mocking support
  • 🔄 Original implementation call-through
  • 📦 Zero runtime dependencies
  • 🔍 Comprehensive error handling
  • 🧪 Async function support
  • 🎨 Deep object comparison
  • 🔧 Chainable API

Table of Contents

Installation

# Using pnpm (recommended)
pnpm add -D @corez/mocker

# Using npm
npm install --save-dev @corez/mocker

# Using yarn
yarn add -D @corez/mocker

Requirements

  • Node.js 16.0.0 or later
  • TypeScript 5.0.0 or later

Quick Start

import {mocker} from '@corez/mocker';

// Mock a simple function
const fn = mocker.fn();
fn.mockReturnValue(42);
console.log(fn()); // 42

// Mock an object with call tracking
const user = {getName: () => 'John'};
const mockedUser = mocker.object(user);
mockedUser.getName.mockReturnValue('Jane');
console.log(mockedUser.getName()); // Jane
console.log(mockedUser.getName.mock.calls.length); // 1

// Mock a class with instance tracking
class UserService {
  getUser(id: number) {
    return {id, name: 'John'};
  }
}
const MockedService = mocker.class(UserService);
const instance = new MockedService();
instance.getUser.mockReturnValue({id: 1, name: 'Jane'});
console.log(MockedService.mock.instances.length); // 1

Basic Usage

Function Mocking

// Basic mock function
const fn = mocker.fn();

// With implementation
const fn = mocker.fn((x: number) => x * 2);

// Return values
fn.mockReturnValue(42);
fn.mockReturnValueOnce(1);
fn.mockReturnValueOnce(2).mockReturnValue(3);

// Implementations
fn.mockImplementation(x => x * 2);
fn.mockImplementationOnce(x => x + 1);

// Async functions
const asyncFn = mocker.fn(async () => 'result');
asyncFn.mockResolvedValue('mocked');
asyncFn.mockRejectedValue(new Error('failed'));

// Reset and verification
fn.mockClear(); // Clear calls
fn.mockReset(); // Clear calls and implementation

Object Mocking

interface User {
  id: number;
  name: string;
  getFullName(): string;
}

const user: User = {
  id: 1,
  name: 'John',
  getFullName: () => 'John Doe',
};

// Mock with type safety
const mockedUser = mocker.object<User>(user);

// Mock methods
mockedUser.getFullName.mockReturnValue('Jane Doe');

// Call through to original implementation
const mockedWithCallThrough = mocker.object(user, {callThrough: true});
console.log(mockedWithCallThrough.getFullName()); // 'John Doe'

// Reset mocks
mockedUser.mockReset();

Class Mocking

class UserService {
  private api: ApiClient;

  constructor(api: ApiClient) {
    this.api = api;
  }

  async getUser(id: number): Promise<User> {
    return this.api.fetch(`/users/${id}`);
  }
}

// Mock entire class
const MockedService = mocker.class(UserService);
const instance = new MockedService();

// Mock specific method
instance.getUser.mockResolvedValue({id: 1, name: 'John'});

// Custom implementation
MockedService.mockImplementation(
  class extends UserService {
    async getUser(id: number) {
      return {id, name: 'Custom'};
    }
  },
);

// Reset class
MockedService.mockReset();

Instance Mocking

class User {
  constructor(public name: string) {}
  getName() {
    return this.name;
  }
}

// Create mocked instance with overrides
const mockedUser = mocker.instance(User, {
  name: 'Jane',
  getName: () => 'Jane Doe',
});

// Mock existing instance
const user = new User('John');
const mockedExisting = mocker.instance(user);

Advanced Usage

Call Through Behavior

class Calculator {
  add(a: number, b: number) {
    return a + b;
  }
}

// Mock with call through
const mockedCalc = mocker.object(new Calculator(), {
  callThrough: true,
});

// Calls original implementation
console.log(mockedCalc.add(2, 3)); // 5

// Still tracks calls
console.log(mockedCalc.add.mock.calls); // [[2, 3]]

Keeping Original Methods

const obj = {
  method1() {
    return 1;
  },
  method2() {
    return 2;
  },
};

// Keep specific methods original
const mocked = mocker.object(obj, {
  keepOriginal: ({property}) => property === 'method1',
});

// method1 remains original, method2 is mocked
console.log(mocked.method1()); // 1
console.log(mocked.method2()); // undefined

Assertions

@corez/mocker provides a powerful assertion API with various matching patterns and detailed error reporting.

Basic Assertions

// Call count assertions
assert.called(spy); // Called at least once
assert.notCalled(spy); // Never called
assert.calledOnce(spy); // Called exactly once
assert.calledTwice(spy); // Called exactly twice
assert.calledThrice(spy); // Called exactly three times
assert.callCount(spy, n); // Called n times

// Argument assertions
assert.calledWith(spy, ...args); // Called with matching arguments
assert.calledWithExactly(spy, ...args); // Called with exact arguments
assert.calledOnceWith(spy, ...args); // Called once with matching arguments

Matchers

@corez/mocker supports three types of matchers:

  1. Built-in Matchers
import {matchers} from '@corez/mocker';

// Type matching
assert.calledWith(
  spy,
  matchers.string(), // Match any string
  matchers.number(), // Match any number
  matchers.boolean(), // Match any boolean
  matchers.any(), // Match any value
);

// Array matching
assert.calledWith(
  spy,
  matchers.arrayContaining([1, 2]), // Array contains specified elements
);

// Object matching
assert.calledWith(
  spy,
  matchers.objectContaining({
    // Object contains specified properties
    id: matchers.number(),
    name: matchers.string(),
  }),
);
  1. Jest-style Matchers
assert.calledWith(spy,
  expect.any(Number),              // Type matching
  expect.stringMatching(/test/),   // RegExp matching
  expect.objectContaining({...}),  // Object containing
  expect.arrayContaining([...])    // Array containing
);
  1. Custom Matchers
assert.calledWith(spy, {
  asymmetricMatch: actual => actual.startsWith('test'),
});

Deep Matching

Support for nested objects and arrays deep matching:

assert.calledWith(spy, {
  user: {
    id: matchers.number(),
    profile: {
      name: matchers.string(),
      tags: matchers.arrayContaining(['admin']),
      meta: matchers.objectContaining({
        verified: matchers.boolean(),
      }),
    },
  },
});

Error Assertions

Multiple error matching patterns:

// String matching
assert.threw(spy, 'error message');

// RegExp matching
assert.threw(spy, /error/);

// Constructor matching
assert.threw(spy, TypeError);

// Property matching
assert.threw(spy, {
  message: 'error message',
  code: 'ERR_001',
});

// Custom matching
assert.threw(spy, {
  asymmetricMatch: error => error.code === 'ERR_001',
});

Context Assertions

// this context assertions
assert.calledOn(spy, thisValue);

// Constructor call assertions
assert.calledWithNew(spy);

Error Formatting

When assertions fail, detailed error reports are generated:

// Call: spy({name: 'test', age: 25})
assert.calledWith(spy, {
  name: 'other',
  age: 30,
});

// Error message:
// AssertionError: expected spy to have been called with specific arguments
// Call 1:
// Expected: [{"name":"other","age":30}]
// Received: [{"name":"test","age":25}]
//
// Difference at index 0:
//   Expected: {"name":"other","age":30}
//   Received: {"name":"test","age":25}

Best Practices

  1. Reset Mocks Between Tests
beforeEach(() => {
  mocker.reset(mockedFunction);
  mockedObject.mockReset();
  MockedClass.mockReset();
});
  1. Type Safety
// Use type parameters for better type inference
const fn = mocker.fn<(x: number) => string>();
const obj = mocker.object<UserService>(service);
  1. Avoid Over-mocking
// Bad: Mocking everything
const mockedService = mocker.object(service);

// Good: Mock only what you need
const mockedService = mocker.object(service, {
  keepOriginal: ['helper1', 'helper2'],
});
  1. Use Call Through When Needed
// Only mock what needs to be mocked
const mockedService = mocker.object(service, {
  callThrough: true,
  keepOriginal: ['util1', 'util2'],
});

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

License

This project is licensed under the Apache-2.0 License - see the LICENSE file for details.