{"id":12182,"library":"ts-mock-imports","title":"Typescript Mock Imports","description":"ts-mock-imports provides an intuitive way to mock ES6 `import` dependencies for TypeScript classes during unit testing, without requiring explicit dependency injection. It is built on top of `sinon` for stubbing capabilities and leverages TypeScript's module resolution to intercept imported classes. The library is currently at version 1.3.19 and primarily sees minor patch releases, focusing on dependency updates and bug fixes rather than rapid feature additions, indicating a mature and stable codebase. A key differentiator is its direct manipulation of imported modules to replace original classes with type-safe stub versions, enabling seamless testing of code that directly instantiates its dependencies. It intercepts and replaces actual class constructors or functions exported via ES6 `import` statements with Sinon stubs at runtime, allowing fine-grained control over dependencies without modifying the source code under test. It requires both `sinon` (version >= 4.1.2) and `typescript` (version >= 2.6.1) as peer dependencies to function correctly.","status":"active","version":"1.3.19","language":"javascript","source_language":"en","source_url":"https://github.com/EmandM/ts-mock-imports","tags":["javascript","import","mock","stub","typescript","dependency","injection","di","require"],"install":[{"cmd":"npm install ts-mock-imports","lang":"bash","label":"npm"},{"cmd":"yarn add ts-mock-imports","lang":"bash","label":"yarn"},{"cmd":"pnpm add ts-mock-imports","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core mocking and stubbing functionality.","package":"sinon","optional":false},{"reason":"Required for type safety and compilation.","package":"typescript","optional":false}],"imports":[{"note":"ImportMock is the main entry point for creating mocks and should be imported as a named export. While the library itself might be callable via CommonJS in some build environments, the core mocking mechanism primarily operates on ES6 `import`s.","wrong":"const { ImportMock } = require('ts-mock-imports');","symbol":"ImportMock","correct":"import { ImportMock } from 'ts-mock-imports';"},{"note":"MockManager is a type interface for the object returned by `ImportMock.mockClass`. It should be imported as a type, not a value, to avoid potential runtime issues or unnecessary bundle size.","wrong":"import { MockManager } from 'ts-mock-imports';","symbol":"MockManager","correct":"import type { MockManager } from 'ts-mock-imports';"},{"note":"InPlaceMockManager is an alternative manager for specific scenarios, particularly when encountering 'Cannot set property' errors due to module getters. It's used for mocking imports where standard `ImportMock.mockClass` fails.","wrong":"const { InPlaceMockManager } = require('ts-mock-imports');","symbol":"InPlaceMockManager","correct":"import { InPlaceMockManager } from 'ts-mock-imports';"}],"quickstart":{"code":"import { ImportMock } from 'ts-mock-imports';\nimport { Bar } from '../src/bar';\nimport * as fooModule from '../src/foo';\n\n// Imagine 'Foo' class in '../src/foo.ts' has a constructor that throws an error\n// and 'Bar' in '../src/bar.ts' instantiates 'Foo'.\n\ndescribe('Bar', () => {\n  let mockFooManager: ImportMock.MockManager<any>;\n\n  beforeEach(() => {\n    // Mock the 'Foo' class from 'fooModule'\n    // This intercepts any 'new Foo()' call within modules that imported fooModule\n    mockFooManager = ImportMock.mockClass(fooModule, 'Foo');\n  });\n\n  afterEach(() => {\n    // Restore all mocks to their original implementations to ensure test isolation\n    ImportMock.restore();\n  });\n\n  it('should create an instance of Bar without error when Foo is mocked', () => {\n    // Now, new Bar() will use the mocked Foo, preventing the error\n    const bar = new Bar();\n    expect(bar).toBeInstanceOf(Bar);\n  });\n\n  it('should allow stubbing methods of the mocked Foo class', () => {\n    // Configure a mock response for the 'getCount' method of Foo\n    mockFooManager.mock('getCount', () => 42);\n\n    // If Bar were to call getCount internally, it would now return 42\n    // For demonstration, let's assume Bar had a method that called Foo.getCount()\n    // (This example focuses on the core mocking setup)\n    // const bar = new Bar();\n    // const result = bar.getFooCount(); // Assuming such a method exists\n    // expect(result).toBe(42);\n    \n    const mockFooInstance = mockFooManager.get;// For a real test, you'd test Bar's interaction with Foo\n  });\n});","lang":"typescript","description":"Demonstrates mocking a TypeScript class imported via ES6 syntax, replacing its constructor and methods with stubs to prevent execution of original logic and control return values."},"warnings":[{"fix":"Standardize module import paths across your project, often by using `tsconfig.json` `paths` aliases, or ensure relative paths are identical between consumer and test files.","message":"When mocking a module, both the source file and the test file must use the *exact same path* to import the target module. Inconsistent import paths (e.g., `'./src/foo'` in production vs. `'src/index'` in tests for the same module) will prevent the mock from being applied correctly.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For modules exhibiting this error, use `InPlaceMockManager` instead of `ImportMock.mockClass`. This manager is designed to work around the getter issue. Example: `const mockManager = new InPlaceMockManager(fooModule, 'Foo');`","message":"TypeScript versions 3.9 and later introduced changes that can cause a `TypeError: Cannot set property TestClass of #<Object> which has only a getter` when attempting to mock certain modules. This occurs because module exports are no longer enumerable, preventing `ts-mock-imports` from replacing the exported class.","severity":"breaking","affected_versions":">=1.3.0"},{"fix":"Always include `ImportMock.restore()` in an `afterEach` or `afterAll` hook in your test setup to reset the module state.","message":"It is critical to call `ImportMock.restore()` after each test or test suite where mocks were applied. Failure to restore mocks can lead to global state pollution, causing tests to interfere with each other and produce flaky or incorrect results.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Be aware that complex module bundlers (e.g., Webpack, Rollup) or newer Node.js ESM loading behaviors might introduce challenges. Consider alternative dependency injection patterns if encountering consistent issues, or ensure your testing environment aligns with the library's assumptions about module loading.","message":"While `ts-mock-imports` allows mocking ES6 `import`s, it relies on runtime manipulation of module exports. This mechanism is fundamentally a 'monkey patch' over Node's module system and may be less robust or compatible with native ESM environments where imports are often immutable.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure `npm install sinon typescript --save-dev` has been run in your project.","message":"`ts-mock-imports` depends on `sinon` and `typescript` as peer dependencies. These must be installed manually in your project (typically as `devDependencies`) for the library to function correctly.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Replace `ImportMock.mockClass` with `new InPlaceMockManager(module, 'ClassName');` to use an alternative mocking strategy that bypasses the getter restriction.","cause":"Attempting to mock a class from a module that defines its exports with getters, preventing modification. This is common with certain TypeScript compilation targets or bundler configurations (e.g., Babel 7+, Webpack).","error":"TypeError: Cannot set property TestClass of #<Object> which has only a getter"},{"fix":"Verify that `import * as myModule from './path/to/module';` in your test file uses the exact same relative or aliased path as the file that imports `ClassName` in your application code.","cause":"The module path provided to `ImportMock.mockClass` in your test file does not precisely match the path used by the module under test that imports `ClassName`.","error":"ReferenceError: [ClassName] is not defined"},{"fix":"Install the required peer dependencies: `npm install sinon typescript --save-dev`.","cause":"The peer dependencies `sinon` and/or `typescript` are not installed in the project.","error":"Cannot find module 'sinon' or Cannot find module 'typescript'"},{"fix":"Ensure the module you are trying to mock is indeed exporting a class via ES6 `export class MyClass { ... }` or `export default class MyClass { ... }` and is being consumed via `import` statements. The library is not compatible with `requirejs`.","cause":"`ts-mock-imports` is designed for mocking ES6 `import`s of classes. This error can occur if you're trying to mock a CommonJS `require`'d module, or if the export structure doesn't match an ES6 class export.","error":"TypeError: module.exports is not a function or module.exports.default is not a constructor"}],"ecosystem":"npm"}