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

ts-mockery

v2.0.0

Published

Yet another typescript mocking library.

Downloads

143,367

Readme

ts-mockery

npm version Build Status Test Coverage Maintainability

Simple, type-safe mocking library for TypeScript

Create type-safe mocks with full IntelliSense support, nested object mocking, and automatic spy setup. Works seamlessly with Jest and Jasmine.

📚 Interactive Examples on StackBlitz

Table of Contents

Installation

npm install --save-dev ts-mockery

Requirements:

  • TypeScript 4.5+
  • Jest or Jasmine testing framework

Quick Start

import { Mock } from 'ts-mockery';

interface UserService {
  getUser(id: number): Promise<{ id: number; name: string; email: string }>;
  updateUser(user: { id: number; name: string }): void;
}

// Create a type-safe mock
const userServiceMock = Mock.of<UserService>({
  getUser: () => Promise.resolve({ id: 1, name: 'John' }), // email is optional
  updateUser: Mock.noop // Auto-spied function
});

// Use in tests
const result = await userServiceMock.getUser(1);
expect(result.id).toBe(1);
expect(userServiceMock.updateUser).toHaveBeenCalled();

Why ts-mockery?

🔒 Type Safety First

  • Full TypeScript support with IntelliSense
  • Compile-time error detection
  • Partial object support with RecursivePartial<T>

🎯 Developer Experience

  • Intuitive API design
  • Automatic spy setup for mocked functions
  • Deep nested object mocking
  • Promise-aware type handling

🧪 Testing Framework Agnostic

  • Works with Jest and Jasmine
  • Consistent API across frameworks
  • Easy configuration and setup

⚡ Advanced Features

  • Static method mocking
  • Circular reference handling
  • Proxy-based lazy mocking
  • Comprehensive Promise support

Core Features

Creating Mocks

Basic Mocking

interface ApiClient {
  baseUrl: string;
  timeout: number;
  request(path: string): Promise<any>;
}

// Create a partial mock - only specify what you need
const apiMock = Mock.of<ApiClient>({
  baseUrl: 'https://api.example.com',
  request: () => Promise.resolve({ data: 'test' })
});
// timeout is automatically undefined (optional)

Nested Object Mocking

interface UserProfile {
  user: {
    id: number;
    profile: {
      name: string;
      email: string;
      preferences: {
        theme: string;
        notifications: boolean;
      };
    };
  };
}

const profileMock = Mock.of<UserProfile>({
  user: {
    id: 1,
    profile: {
      name: 'John',
      // email is optional
      preferences: {
        theme: 'dark'
        // notifications is optional
      }
    }
  }
});

Array Mocking

interface DataService {
  users: Array<{ id: number; name: string; active: boolean }>;
  tags: string[];
}

const dataMock = Mock.of<DataService>({
  users: [
    { id: 1, name: 'John' }, // active is optional
    { id: 2, name: 'Jane', active: true }
  ],
  tags: ['typescript', 'testing']
});

Updating Mocks

interface Calculator {
  add(a: number, b: number): number;
  multiply(a: number, b: number): number;
  history: number[];
}

const calculator = Mock.of<Calculator>({
  add: (a, b) => a + b,
  history: []
});

// Update the mock with additional properties
Mock.extend(calculator).with({
  multiply: (a, b) => a * b,
  history: [1, 2, 3]
});

Promise Support

ts-mockery provides full Promise support with type-safe partial resolved values:

interface ApiService {
  fetchUser(
    id: number
  ): Promise<{
    id: number;
    name: string;
    email: string;
    profile: { avatar: string };
  }>;
  updateUser(data: {
    name: string;
  }): Promise<{ success: boolean; message: string }>;
  deleteUser(id: number): Promise<void>;
}

const apiMock = Mock.of<ApiService>({
  // Promise resolved values support partial objects
  fetchUser: () =>
    Promise.resolve({
      id: 1,
      name: 'John'
      // email and profile are optional due to RecursivePartial
    }),

  // Return minimal required data
  updateUser: () => Promise.resolve({ success: true }),

  // Void promises work seamlessly
  deleteUser: () => Promise.resolve()
});

Nested Promise Support

interface ComplexService {
  processData(): Promise<{
    result: {
      data: { id: number; value: string };
      metadata: { timestamp: Date; version: number };
    };
  }>;
}

const serviceMock = Mock.of<ComplexService>({
  processData: () =>
    Promise.resolve({
      result: {
        data: { id: 1, value: 'test' }
        // metadata is optional
      }
    })
});

Static Method Mocking

class FileUtils {
  static readFile(path: string): string {
    // Implementation
  }

  static writeFile(path: string, content: string): void {
    // Implementation
  }
}

// Mock static methods
Mock.staticMethod(FileUtils, 'readFile', () => 'mocked content');
Mock.staticMethod(FileUtils, 'writeFile', Mock.noop);

// Use in tests
const content = FileUtils.readFile('/path/to/file');
expect(content).toBe('mocked content');

Mocking Imported Modules

You can also mock functions from imported modules:

// utils.ts
export const calculateTax = (amount: number) => amount * 0.1;
export const formatCurrency = (amount: number) => `$${amount.toFixed(2)}`;

// In your test file
import * as Utils from './utils';
import { Mock } from 'ts-mockery';

// Mock specific functions from imported modules
Mock.staticMethod(Utils, 'calculateTax', () => 5.0);
Mock.staticMethod(Utils, 'formatCurrency', (amount) => `€${amount}`);

// Use in tests
const tax = Utils.calculateTax(100);
const formatted = Utils.formatCurrency(50);

expect(tax).toBe(5.0);
expect(formatted).toBe('€50');
expect(Utils.calculateTax).toHaveBeenCalledWith(100);

Utility Functions

Mock.noop - No-op Functions

interface EventHandler {
  onClick: () => void;
  onSubmit: (data: any) => void;
  onError: (error: Error) => void;
}

const handlerMock = Mock.of<EventHandler>({
  onClick: Mock.noop, // Automatically spied
  onSubmit: Mock.noop, // Automatically spied
  onError: Mock.noop // Automatically spied
});

// All functions are spied and can be tested
expect(handlerMock.onClick).toHaveBeenCalled();

Mock.all - Proxy-based Lazy Mocking

interface LargeService {
  method1(): string;
  method2(): number;
  method3(): boolean;
  // ... many more methods
}

// Creates spies on-demand as methods are accessed
const serviceMock = Mock.all<LargeService>();

// Only creates spy when first accessed
const result = serviceMock.method1();
expect(serviceMock.method1).toHaveBeenCalled();

Mock.from - Handling Complex Objects

Use Mock.from when dealing with:

  • Class inheritance hierarchies
  • Objects with circular references (e.g., RxJS Observables)
  • Complex prototype chains
class BaseService {
  protected baseMethod(): void {}
}

class UserService extends BaseService {
  getUser(): User {}
}

// Mock.of might not handle inheritance correctly
const mock1 = Mock.of<UserService>(new BaseService()); // ❌ May have issues

// Mock.from handles inheritance and circular references
const mock2 = Mock.from<UserService>(new BaseService()); // ✅ Works correctly

Circular Reference Handling:

import { of } from 'rxjs';

interface ReactiveService {
  data$: Observable<any>;
}

// Mock.of might throw RangeError with circular references
const mock1 = Mock.of<ReactiveService>({ data$: of(someValue) }); // ❌ May throw

// Mock.from handles circular references safely
const mock2 = Mock.from<ReactiveService>({ data$: of(someValue) }); // ✅ Works

Configuration

Set up ts-mockery in your test configuration:

Jest Setup

Create a setup file (e.g., jest-setup.ts):

import { Mock } from 'ts-mockery';

Mock.configure('jest');

Add to your jest.config.js:

module.exports = {
  setupFiles: ['<rootDir>/jest-setup.ts'],
  restoreMocks: true // Important: Required for static method mocking
};

Jasmine Setup

Add to your Karma configuration or test setup:

import { Mock } from 'ts-mockery';

Mock.configure('jasmine');

Custom Spy Adapter

import { Mock, SpyAdapter } from 'ts-mockery';

const customAdapter: SpyAdapter = {
  getSpy: (property: string) => /* custom spy implementation */,
  spyAndCallFake: (object, key, stub) => /* custom spy setup */,
  spyAndCallThrough: (object, key) => /* custom spy setup */
};

Mock.configure(customAdapter);

API Reference

Mock.of(stubs?: RecursivePartial): T

Creates a mock object with optional property stubs.

Mock.extend(object: T): ExtendedWith

Returns an object with a .with() method for updating mocks.

Mock.from(object: RecursivePartial): T

Creates a mock handling complex objects and circular references.

Mock.staticMethod<T, K>(object: T, key: K, stub: Function): void

Mocks a static method on a class or function from an imported module.

Mock.noop: () => any

Returns a no-op function that is automatically spied.

Mock.all(): T

Creates a proxy-based mock that generates spies on-demand.

Mock.configure(adapter: 'jest' | 'jasmine' | SpyAdapter): void

Configures the underlying spy framework.

Advanced Usage

Working with Generic Types

interface Repository<T> {
  find(id: string): Promise<T>;
  save(entity: T): Promise<void>;
  delete(id: string): Promise<boolean>;
}

interface User {
  id: string;
  name: string;
  email: string;
}

const userRepo = Mock.of<Repository<User>>({
  find: () => Promise.resolve({ id: '1', name: 'John' }), // email optional
  save: Mock.noop,
  delete: () => Promise.resolve(true)
});

Conditional Mocking

interface ConfigService {
  isFeatureEnabled(feature: string): boolean;
  getConfig(): { env: string; debug: boolean; apiUrl: string };
}

const configMock = Mock.of<ConfigService>({
  isFeatureEnabled: (feature) => feature === 'newFeature',
  getConfig: () => ({ env: 'test', debug: true }) // apiUrl optional
});

Method Chaining

interface FluentBuilder {
  withName(name: string): FluentBuilder;
  withAge(age: number): FluentBuilder;
  build(): { name: string; age: number };
}

const builderMock = Mock.of<FluentBuilder>({
  withName: function (name) {
    return this;
  },
  withAge: function (age) {
    return this;
  },
  build: () => ({ name: 'test', age: 25 })
});

Troubleshooting

Common Issues

TypeScript Errors with Deep Nesting

// ❌ May cause complex type errors
const deepMock = Mock.of<VeryComplexNestedType>({
  /* complex object */
});

// ✅ Use type assertion for complex cases
const deepMock = Mock.of<VeryComplexNestedType>({
  /* simpler object */
} as any);

Circular Reference Errors

// ❌ May throw RangeError
const mock = Mock.of<ServiceWithObservables>({ data$: of(value) });

// ✅ Use Mock.from instead
const mock = Mock.from<ServiceWithObservables>({ data$: of(value) });

Static Method Mocking Not Working

  • Ensure restoreMocks: true in Jest configuration
  • Make sure Mock.configure() is called before tests
  • Static method mocking requires proper spy framework setup

Module Import Mocking Issues

  • Import modules using import * as Module from './module' syntax for best results
  • Ensure the imported module is not tree-shaken or optimized away
  • Module mocking works best with functions exported at the module level

Promise Type Issues

// ✅ Promise resolved values automatically support partial objects
const mock = Mock.of<ApiService>({
  getUser: () => Promise.resolve({ id: 1 }) // name, email, etc. are optional
});

Performance Considerations

  • Use Mock.all() for large interfaces where you only need a few methods
  • Prefer Mock.of() over Mock.from() when possible (better performance)
  • Consider using Mock.noop for methods you don't need to test

Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

git clone https://github.com/ike18t/ts-mockery.git
cd ts-mockery
npm install
npm test

Running Tests

npm run test:jest    # Run Jest tests
npm run test:jasmine # Run Jasmine tests
npm test             # Run all tests

Made with ❤️ by the TypeScript community

For more examples and advanced usage, visit our StackBlitz Examples.