Type safe mocking extensions for jest
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Core mock creation functionality for interfaces and classes with full TypeScript type safety and Jest integration.
Creates a type-safe mock proxy for any interface or class, preserving TypeScript type information while adding Jest mock functionality.
/**
* Creates a type-safe mock proxy for interfaces and classes
* @param mockImplementation - Optional partial implementation to override default behavior
* @param opts - Configuration options for mock behavior
* @returns Type-safe mock proxy with Jest functionality
*/
function mock<T>(
mockImplementation?: DeepPartial<T>,
opts?: MockOpts
): MockProxy<T> & T;
interface MockOpts {
/** Enable deep mocking for nested objects */
deep?: boolean;
/** Fallback implementation when no expectation is set */
fallbackMockImplementation?: (...args: any[]) => any;
}Usage Examples:
import { mock, MockProxy } from "jest-mock-extended";
interface PaymentService {
processPayment: (amount: number, cardId: string) => Promise<PaymentResult>;
validateCard: (cardId: string) => boolean;
refundPayment: (paymentId: string) => Promise<void>;
}
// Basic mock creation
const paymentService = mock<PaymentService>();
// Mock with partial implementation
const paymentServiceWithDefaults = mock<PaymentService>({
validateCard: jest.fn().mockReturnValue(true)
});
// Mock with fallback implementation
const strictPaymentService = mock<PaymentService>({}, {
fallbackMockImplementation: () => {
throw new Error("Mock not configured for this call");
}
});Type definition that adds calledWith extension to function properties while preserving original type structure.
/**
* Type-safe mock proxy that extends original type with Jest mock functionality
*/
type MockProxy<T> = _MockProxy<T> & T;
type _MockProxy<T> = {
[K in keyof T]: T[K] extends FunctionLike
? T[K] & CalledWithMock<T[K]>
: T[K];
};Usage Examples:
import { MockProxy, mock } from "jest-mock-extended";
interface DatabaseService {
findUser: (id: string) => Promise<User>;
saveUser: (user: User) => Promise<void>;
}
// Properly typed mock variable
let dbService: MockProxy<DatabaseService>;
beforeEach(() => {
dbService = mock<DatabaseService>();
});
test("should save user", async () => {
// Full type safety and calledWith functionality
dbService.saveUser.calledWith(expect.any(Object)).mockResolvedValue();
await dbService.saveUser({ id: "123", name: "John" });
expect(dbService.saveUser).toHaveBeenCalledWith({ id: "123", name: "John" });
});Extended Jest mock interface that adds argument-specific expectation functionality through the calledWith method.
/**
* Jest mock extended with argument-specific expectations
*/
interface CalledWithMock<T extends FunctionLike> extends jest.Mock<T> {
/**
* Creates argument-specific expectation for mock function
* @param args - Expected arguments (can use matchers or literal values)
* @returns Jest mock for chaining expectations
*/
calledWith: (...args: [...MatchersOrLiterals<Parameters<T>>]) => jest.Mock<T>;
}Usage Examples:
import { mock, any, anyString } from "jest-mock-extended";
interface EmailService {
sendEmail: (to: string, subject: string, body: string) => Promise<boolean>;
}
const emailService = mock<EmailService>();
// Argument-specific expectations
emailService.sendEmail
.calledWith("admin@example.com", anyString(), any())
.mockResolvedValue(true);
emailService.sendEmail
.calledWith("invalid@email", any(), any())
.mockResolvedValue(false);
// Test behavior
expect(await emailService.sendEmail("admin@example.com", "Hello", "World")).toBe(true);
expect(await emailService.sendEmail("invalid@email", "Test", "Body")).toBe(false);Creates a standalone Jest function mock with calledWith extension, useful for mocking individual functions.
/**
* Creates a Jest function mock with calledWith extension
* @returns Typed mock function with argument matching capabilities
*/
function mockFn<T extends FunctionLike>(): CalledWithMock<T> & T;Usage Examples:
import { mockFn } from "jest-mock-extended";
type CalculatorFn = (a: number, b: number) => number;
// Create standalone function mock
const calculateFn = mockFn<CalculatorFn>();
// Set up argument-specific behavior
calculateFn.calledWith(1, 2).mockReturnValue(3);
calculateFn.calledWith(5, 5).mockReturnValue(10);
// Use in tests
expect(calculateFn(1, 2)).toBe(3);
expect(calculateFn(5, 5)).toBe(10);
expect(calculateFn).toHaveBeenCalledTimes(2);