mock() and stub()
Create type-safe mocks and stubs for any TypeScript code. Works without dependency injection frameworks.
Standalone utility functions for creating type-safe mocks. Works with any TypeScript code, with or without dependency injection frameworks.
When to Use
Use mock() and stub() functions when:
- Testing code without dependency injection frameworks
- Creating standalone test doubles outside of
TestBed - Testing plain TypeScript classes, functions, or modules
- You’re comfortable with manual dependency wiring
mock()
Creates a fully mocked instance with auto-generated stub methods. This standalone function creates mocks manually,
outside of TestBed.
Signature
function mock<T>(mockImplementation: DeepPartial<T> = {}): Mocked<T>Parameters
| Parameter | Type | Description |
|---|---|---|
mockImplementation | DeepPartial<T> | Optional partial implementation to pre-configure the mock |
Returns
Mocked<T> - A deeply mocked instance where all methods are automatically stubbed.
How It Works
mock() returns a Proxy that intercepts property access. When you access a method for the first time, it automatically creates a stub function (jest.fn(), vi.fn(), or sinon.stub() depending on your adapter).
import { mock } from '@suites/unit';
const userRepo = mock<UserRepository>();
// Methods auto-generated on first accessuserRepo.findById.mockResolvedValue(testUser);userRepo.save.mockResolvedValue(savedUser);
// Nested objects work toouserRepo.database.connect.mockResolvedValue(true);Basic Usage
import { mock } from '@suites/unit';
interface PaymentGateway { charge(amount: number): Promise<{ status: string }>; refund(transactionId: string): Promise<void>; validate(card: Card): boolean;}
const gateway = mock<PaymentGateway>();
// Configure methods as neededgateway.charge.mockResolvedValue({ status: "success" });gateway.refund.mockResolvedValue(undefined);gateway.validate.mockReturnValue(true);
// Use in testsconst result = await gateway.charge(100);expect(result.status).toBe("success");expect(gateway.charge).toHaveBeenCalledWith(100);Manual Testing (Non-DI)
mock() works with plain TypeScript classes, no decorators or DI containers required:
// Plain TypeScript class (no @Injectable decorator)class UserService { constructor( private repository: UserRepository, private logger: Logger ) {}
async getUser(id: number): Promise<User> { this.logger.log(`Fetching user ${id}`); return this.repository.findById(id); }}
// Create mocksconst mockRepository = mock<UserRepository>();const mockLogger = mock<Logger>();
// Manual wiring - you track the mock referencesconst userService = new UserService(mockRepository, mockLogger);
// Configure mock behaviormockRepository.findById.mockResolvedValue({ id: 1, name: "John" });
// Test the serviceconst user = await userService.getUser(1);expect(user.name).toBe("John");expect(mockLogger.log).toHaveBeenCalledWith("Fetching user 1");Note: You manually wire dependencies and track mock references (mockRepository, mockLogger). With TestBed, this happens automatically.
With Pre-Configuration
You can provide a partial implementation upfront:
const gateway = mock<PaymentGateway>({ charge: async (amount) => ({ status: amount > 0 ? "success" : "failed" }), validate: (card) => card.number.length === 16,});
// Pre-configured methods work immediatelyawait gateway.charge(100); // Returns { status: "success" }
// Other methods still auto-generategateway.refund.mockResolvedValue(undefined);Nested Object Mocking
mock() handles deeply nested structures:
interface DatabaseService { users: { find(id: string): Promise<User>; save(user: User): Promise<void>; delete(id: string): Promise<boolean>; }; orders: { create(order: Order): Promise<Order>; list(): Promise<Order[]>; };}
const db = mock<DatabaseService>();
// Nested methods auto-generateddb.users.find.mockResolvedValue(testUser);db.users.save.mockResolvedValue(undefined);db.users.delete.mockResolvedValue(true);db.orders.create.mockResolvedValue(testOrder);db.orders.list.mockResolvedValue([testOrder]);stub()
Creates a single standalone stub function (not a full object mock).
Signature
Jest
function stub<TArgs extends any[] = any[]>(): jest.Mock<any, TArgs>Vitest
function stub<TArgs extends any[] = any[]>(): Mock<any, TArgs>Sinon
function stub<TArgs extends any[] = any[]>(): SinonStubReturns
A mock function from your testing framework.
Basic Usage
import { stub } from "@suites/unit";
// Create standalone stubconst mockFn = stub();mockFn.mockReturnValue(42);
const result = mockFn();expect(result).toBe(42);expect(mockFn).toHaveBeenCalled();Callback Mocking
interface EventEmitter { on(event: string, callback: (data: any) => void): void; emit(event: string, data: any): void;}
const emitter = mock<EventEmitter>();const callbackStub = stub();
// Register callbackemitter.on("data", callbackStub);
// Simulate event (in real code)emitter.emit("data", { value: 123 });
// Verify callback was invokedexpect(callbackStub).toHaveBeenCalledWith({ value: 123 });Function Dependency Injection
Test classes that accept functions as dependencies:
class PriceCalculator { constructor(private taxRateFn: () => number) {}
calculate(price: number) { return price * (1 + this.taxRateFn()); }}
// Mock the function dependencyconst taxRateStub = stub().mockReturnValue(0.1); // 10% taxconst calculator = new PriceCalculator(taxRateStub);
expect(calculator.calculate(100)).toBe(110);expect(taxRateStub).toHaveBeenCalled();Difference from mock()
| Feature | stub() | mock() |
|---|---|---|
| Creates | Single function | Full object with methods |
| Use case | Function mocking | Object/interface mocking |
| Nesting | N/A | Auto-generates nested properties |
| Pre-config | Via .mockReturnValue() etc. | Via partial object |
// stub(): Single functionconst fn = stub();fn.mockReturnValue(42);
// mock(): Full objectconst obj = mock<MyService>();obj.method1.mockReturnValue(42);obj.method2.mockReturnValue(100);See Also
- Types -
Mocked<T>type definition - TestBed.solitary() - Automatic dependency mocking
- TestBed Configuration - Using
.mock().impl()withstub()