Suites
A unit testing framework for TypeScript backends working with inversion of control and dependency injection
by @omermorad
Docs • Getting Started • Why Suites • Guides
Dependency Injection Frameworks: NestJS (official), InversifyJS (official)
Testing Libraries: Jest, Vitest, Sinon
Using Suites? Share your experience, and help us shape the future of Suites
Features
-
Declarative - Provides a declarative API for defining fully-typed, isolated test environments from a single specification, including automatic mock generation and dependency wiring based on constructor metadata.
-
Type-Safe Refactoring - Binds mocks to concrete TypeScript implementations so that changes to constructors, injected dependencies, and method signatures are validated at compile time, enabling confident refactors with less failing tests.
-
Standardized Testing Across Teams - Exposes a uniform testing surface across NestJS, InversifyJS, and other DI setups, enabling consistent test structure and patterns regardless of the underlying framework.
-
AI Ready - Provides a concise and strict test API that minimizes context requirements for LLM-based coding agents, enabling higher-quality generated tests, clearer and more actionable error messages that guide automatic self-correction, and a higher likelihood of completing test authoring in a single pass.
Examples
Solitary Mode
Solitary mode tests a single unit in complete isolation - all dependencies are automatically mocked. Use this when you want to test your unit's logic without any real dependencies.
Learn more about Solitary Tests
import { TestBed, type Mocked } from '@suites/unit'; describe('User Service', () => { let userService: UserService; // Class under test let userApi: Mocked<UserApi>; // Mock instance let database: Mocked<Database>; // Mock instance beforeAll(async () => { // Create the test environment with automatic mocking const testBed = await TestBed.solitary(UserService).compile(); userService = testBed.unit; // Retrieve the mock instances userApi = testBed.unitRef.get(UserApi); database = testBed.unitRef.get(Database); }); it('should generate a random user and save to the database', async () => { const mockUser = { id: 1, name: 'John' } as User; userApi.getRandom.mockResolvedValue(mockUser); await userService.generateRandomUser(); expect(database.saveUser).toHaveBeenCalledWith(mockUser); }); }
How It Works
The test setup uses TestBed.solitary() to create an isolated testing environment:
- TestBed analyzes the class - Reads
UserServiceconstructor to findUserApiandDatabasedependencies - Automatic mocks are created - Generates mock instances of
UserApiandDatabasewith all methods as stubs - Dependencies are injected - Wires the mocks into
UserServiceconstructor automatically - Type-safe access - Use
unitRef.get()to retrieve mocks with full TypeScript support
No manual mock creation needed. TestBed handles dependency discovery, mock generation, and wiring automatically.
Automatic Mocking of Dependencies
When using TestBed.solitary(), all dependencies are automatically mocked. Each method becomes a stub with no predefined responses. Configure stub responses in tests as needed.
// These stubs start with no return values userApi.getRandom // Returns undefined by default database.saveUser // Returns undefined by default // Configure them in your tests userApi.getRandom.mockResolvedValue({ id: 1, name: 'John' }); database.saveUser.mockResolvedValue(42);
Sociable Mode
Sociable mode tests how components work together. You choose which dependencies to keep real (using .expose()) while external I/O remains mocked. Use this when you want to test integration between multiple units.
Learn more about Sociable Tests
import { TestBed, type Mocked } from '@suites/unit'; describe('User Service', () => { let userService: UserService; // Class under test let database: Mocked<Database>; // Mock instance beforeAll(async () => { // Create test environment with real UserApi const testBed = await TestBed.sociable(UserService) .expose(UserApi) // Use real UserApi implementation .compile(); userService = testBed.unit; database = testBed.unitRef.get(Database); }); it('should generate a random user and save to the database', async () => { await userService.generateRandomUser(); expect(database.saveUser).toHaveBeenCalled(); }); }
Prerequisites
Before installing Suites, ensure your project meets these requirements:
- Dependency Injection Framework: NestJS, InversifyJS, or plain TypeScript classes with constructor injection
- Testing Library: Jest, Vitest, or Sinon
Installation
First, install Suites' unit package:
npm i -D @suites/unit # or yarn add -D @suites/unit # or pnpm add -D @suites/unit
Then, install ONE adapter for your DI framework and ONE adapter for your testing library:
DI Framework Adapters:
- NestJS -
@suites/di.nestjs - InversifyJS -
@suites/di.inversify
Testing Library Adapters:
- Jest -
@suites/doubles.jest - Vitest -
@suites/doubles.vitest - Sinon -
@suites/doubles.sinon
Example for NestJS + Jest:
npm i -D @suites/doubles.jest @suites/di.nestjs # or yarn add -D @suites/doubles.jest @suites/di.nestjs # or pnpm add -D @suites/doubles.jest @suites/di.nestjs
Note: If you're using NestJS or Inversify, you'll also need to install
reflect-metadataas a runtime dependency (not a dev dependency):
For complete installation instructions, see the Installation Guide.
Configuration
Type Definitions
Create a global.d.ts file in your project root (or in your test directory) to enable proper TypeScript support:
/// <reference types='@suites/doubles.jest/unit' /> /// <reference types='@suites/di.nestjs/metadata' />
Replace @suites/doubles.jest and @suites/di.nestjs with your chosen adapters.
For detailed configuration instructions, see the Installation Guide.
Contributing
We welcome contributions to Suites! Please see the CONTRIBUTING.md file for more information.
Share Your Suites Experience!
Are you using Suites in your projects? We've created a community discussion where teams and companies can share how they're using Suites in production.
👉 Join the discussion and tell us more :)
Your contributions help others discover best practices and see real-world applications of Suites!
Migrating from Automock
If you're currently using Automock, we've created a comprehensive migration guide to help you transition to Suites. The guide covers all the changes and improvements, making the upgrade process smooth and straightforward.
Your support helps us continue improving Suites and developing new features!
Support the Project
📜 License
Suites is licensed under the Apache License, Version 2.0.

