Yet another typescript mocking library.
npm install ts-mockery



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
- Installation
- Quick Start
- Why ts-mockery?
- Core Features
- Creating Mocks
- Updating Mocks
- Promise Support
- Static Method Mocking
- Mocking Imported Modules
- Utility Functions
- Configuration
- API Reference
- Advanced Usage
- Troubleshooting
- Contributing
``bash`
npm install --save-dev ts-mockery
Requirements:
- TypeScript 4.5+
- Jest or Jasmine testing framework
`typescript
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
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();
`
๐ Type Safety First
- Full TypeScript support with IntelliSense
- Compile-time error detection
- Partial object support with RecursivePartial
๐ฏ 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
#### Basic Mocking
`typescript
interface ApiClient {
baseUrl: string;
timeout: number;
request(path: string): Promise
}
// Create a partial mock - only specify what you need
const apiMock = Mock.of
baseUrl: 'https://api.example.com',
request: () => Promise.resolve({ data: 'test' })
});
// timeout is automatically undefined (optional)
`
#### Nested Object Mocking
`typescript
interface UserProfile {
user: {
id: number;
profile: {
name: string;
email: string;
preferences: {
theme: string;
notifications: boolean;
};
};
};
}
const profileMock = Mock.of
user: {
id: 1,
profile: {
name: 'John',
// email is optional
preferences: {
theme: 'dark'
// notifications is optional
}
}
}
});
`
#### Array Mocking
`typescript
interface DataService {
users: Array<{ id: number; name: string; active: boolean }>;
tags: string[];
}
const dataMock = Mock.of
users: [
{ id: 1, name: 'John' }, // active is optional
{ id: 2, name: 'Jane', active: true }
],
tags: ['typescript', 'testing']
});
`
`typescript
interface Calculator {
add(a: number, b: number): number;
multiply(a: number, b: number): number;
history: number[];
}
const calculator = Mock.of
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]
});
`
ts-mockery provides full Promise support with type-safe partial resolved values:
`typescript
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
}
const apiMock = Mock.of
// 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
`typescript
interface ComplexService {
processData(): Promise<{
result: {
data: { id: number; value: string };
metadata: { timestamp: Date; version: number };
};
}>;
}
const serviceMock = Mock.of
processData: () =>
Promise.resolve({
result: {
data: { id: 1, value: 'test' }
// metadata is optional
}
})
});
`
`typescript
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:
`typescript$${amount.toFixed(2)}
// utils.ts
export const calculateTax = (amount: number) => amount * 0.1;
export const formatCurrency = (amount: number) => ;
// 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);
`
#### Mock.noop - No-op Functions
`typescript
interface EventHandler {
onClick: () => void;
onSubmit: (data: any) => void;
onError: (error: Error) => void;
}
const handlerMock = Mock.of
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
`typescript
interface LargeService {
method1(): string;
method2(): number;
method3(): boolean;
// ... many more methods
}
// Creates spies on-demand as methods are accessed
const serviceMock = Mock.all
// 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
`typescript
class BaseService {
protected baseMethod(): void {}
}
class UserService extends BaseService {
getUser(): User {}
}
// Mock.of might not handle inheritance correctly
const mock1 = Mock.of
// Mock.from handles inheritance and circular references
const mock2 = Mock.from
`
Circular Reference Handling:
`typescript
import { of } from 'rxjs';
interface ReactiveService {
data$: Observable
}
// Mock.of might throw RangeError with circular references
const mock1 = Mock.of
// Mock.from handles circular references safely
const mock2 = Mock.from
`
Set up ts-mockery in your test configuration:
Create a setup file (e.g., jest-setup.ts):
`typescript
import { Mock } from 'ts-mockery';
Mock.configure('jest');
`
Add to your jest.config.js:
`javascript`
module.exports = {
setupFiles: ['
restoreMocks: true // Important: Required for static method mocking
};
Add to your Karma configuration or test setup:
`typescript
import { Mock } from 'ts-mockery';
Mock.configure('jasmine');
`
`typescript
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);
`
Creates a mock object with optional property stubs.
Returns an object with a .with() method for updating mocks.
Creates a mock handling complex objects and circular references.
Mocks a static method on a class or function from an imported module.
Returns a no-op function that is automatically spied.
Creates a proxy-based mock that generates spies on-demand.
Configures the underlying spy framework.
`typescript
interface Repository
find(id: string): Promise
save(entity: T): Promise
delete(id: string): Promise
}
interface User {
id: string;
name: string;
email: string;
}
const userRepo = Mock.of
find: () => Promise.resolve({ id: '1', name: 'John' }), // email optional
save: Mock.noop,
delete: () => Promise.resolve(true)
});
`
`typescript
interface ConfigService {
isFeatureEnabled(feature: string): boolean;
getConfig(): { env: string; debug: boolean; apiUrl: string };
}
const configMock = Mock.of
isFeatureEnabled: (feature) => feature === 'newFeature',
getConfig: () => ({ env: 'test', debug: true }) // apiUrl optional
});
`
`typescript
interface FluentBuilder {
withName(name: string): FluentBuilder;
withAge(age: number): FluentBuilder;
build(): { name: string; age: number };
}
const builderMock = Mock.of
withName: function (name) {
return this;
},
withAge: function (age) {
return this;
},
build: () => ({ name: 'test', age: 25 })
});
`
TypeScript Errors with Deep Nesting
`typescript
// โ May cause complex type errors
const deepMock = Mock.of
/ complex object /
});
// โ
Use type assertion for complex cases
const deepMock = Mock.of
/ simpler object /
} as any);
`
Circular Reference Errors
`typescript
// โ May throw RangeError
const mock = Mock.of
// โ
Use Mock.from instead
const mock = Mock.from
`
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
`typescript`
// โ
Promise resolved values automatically support partial objects
const mock = Mock.of
getUser: () => Promise.resolve({ id: 1 }) // name, email, etc. are optional
});
- Use Mock.all() for large interfaces where you only need a few methodsMock.of()
- Prefer over Mock.from() when possible (better performance)Mock.noop
- Consider using for methods you don't need to test
We welcome contributions! Please see our Contributing Guide for details.
`bash`
git clone https://github.com/ike18t/ts-mockery.git
cd ts-mockery
npm install
npm test
`bash``
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.