Skip to main content

Types

TypeScript type definitions used throughout Suites.

Core Types

Mocked<T>

A deeply nested mock type. All methods become mock functions, nested objects are mocked recursively.

interface UserService {
repository: {
find(id: string): User;
save(user: User): void;
};
validate(user: User): boolean;
}

const service: Mocked<UserService> = unitRef.get(UserService);

// All methods mocked, including nested
service.validate.mockReturnValue(true);
service.repository.find.mockResolvedValue(testUser);
service.repository.save.mockReturnValue(undefined);

How Mocked<T> Works: Module Augmentation

The Mocked<T> type is always imported from @suites/unit, never from adapter packages. Suites uses TypeScript's module augmentation to automatically provide the correct library-specific types.

Single Import Point

// ✅ Always import from @suites/unit
import { Mocked } from '@suites/unit';

// ❌ Never import from adapter packages
// import { Mocked } from '@suites/doubles.jest'; // Wrong!

Automatic Type Resolution

When an adapter package (like @suites/doubles.jest) is installed, it automatically augments the @suites/unit module with library-specific types:

// @suites/doubles.jest/unit.d.ts (internal - you never see this)
declare module '@suites/unit' {
export type Mocked<T> = jest.Mocked<T>; // Overrides base type
}

This means the same Mocked<T> import resolves to different concrete types based on which adapter is installed.

Zero Configuration

This works automatically when you install an adapter package. No manual configuration needed - TypeScript resolves the correct types based on your installed dependencies.

Why This Architecture Matters

Because Suites is framework agnostic. The same test code works across Jest, Vitest, and Sinon without changes. Only the installed adapter package determines which library-specific types and methods are available.

Maintains Dependency Inversion: The @suites/unit package never depends on adapter packages. Instead, adapters augment the base package - following proper dependency inversion principle.

// This exact code works with any adapter installed
describe('UserService', () => {
let service: UserService;
let database: Mocked<Database>;

beforeAll(async () => {
const { unit, unitRef } = await TestBed.solitary(UserService).compile();
service = unit;

// Return Mocked type corresponding to installed adapter
database = unitRef.get(Database);
});
});

See Also

Morty Proxy This is a proxified and sanitized view of the page, visit original site.