https://github.com/suites-dev/suites
A unit testing framework for TypeScript backends working with inversion of control and dependency injection
https://github.com/suites-dev/suites
dependency-injection inversifyjs inversion-of-control ioc ioc-container jest mock mocking nestjs sinon sinonjs spec tdd testing typescript unit-test unit-testing unit-testing-nodejs vitest
Last synced: 23 days ago
JSON representation
A unit testing framework for TypeScript backends working with inversion of control and dependency injection
- Host: GitHub
- URL: https://github.com/suites-dev/suites
- Owner: suites-dev
- License: apache-2.0
- Created: 2021-11-18T15:13:37.000Z (about 4 years ago)
- Default Branch: master
- Last Pushed: 2025-12-03T20:46:25.000Z (2 months ago)
- Last Synced: 2025-12-04T03:23:25.299Z (2 months ago)
- Topics: dependency-injection, inversifyjs, inversion-of-control, ioc, ioc-container, jest, mock, mocking, nestjs, sinon, sinonjs, spec, tdd, testing, typescript, unit-test, unit-testing, unit-testing-nodejs, vitest
- Language: TypeScript
- Homepage: https://suites.dev
- Size: 4.73 MB
- Stars: 503
- Watchers: 5
- Forks: 21
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
- Security: SECURITY.md
Awesome Lists containing this project
- awesome-jest - Suites - testing framework for TypeScript backends with inversion of control and dependency injection that automatically generates type-safe mocks. (Packages / Mocks)
- awesome-typescript - Suites - Unit testing framework for TypeScript backends working with inversion of control (IoC) and dependency injection frameworks. (Built with TypeScript / Libraries)
README
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](https://suites.dev/docs/guides/solitary)
```typescript
import { TestBed, type Mocked } from '@suites/unit';
describe('User Service', () => {
let userService: UserService; // Class under test
let userApi: Mocked; // Mock instance
let database: Mocked; // 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:
1. **TestBed analyzes the class** - Reads `UserService` constructor to find `UserApi` and `Database` dependencies
2. **Automatic mocks are created** - Generates mock instances of `UserApi` and `Database` with all methods as stubs
3. **Dependencies are injected** - Wires the mocks into `UserService` constructor automatically
4. **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.
```typescript
// 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](https://suites.dev/docs/guides/sociable)
```typescript
import { TestBed, type Mocked } from '@suites/unit';
describe('User Service', () => {
let userService: UserService; // Class under test
let database: Mocked; // 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:
```bash
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:**
```bash
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-metadata` as a runtime dependency (not a dev dependency):
> ```bash
> npm i reflect-metadata
> ```
For complete installation instructions, see the [Installation Guide](https://suites.dev/docs/get-started/installation).
## Configuration
### Type Definitions
Create a `global.d.ts` file in your project root (or in your test directory) to enable proper TypeScript support:
```typescript
///
///
```
Replace `@suites/doubles.jest` and `@suites/di.nestjs` with your chosen adapters.
For detailed configuration instructions, see the [Installation Guide](https://suites.dev/docs/get-started/installation).
### Contributing
We welcome contributions to Suites! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for more information.
## Share Your Suites Experience!
**Are you using Suites in your projects?** We've created a [community discussion](https://github.com/suites-dev/suites/discussions/categories/q-a) where teams and companies can share how they're using Suites in production.
👉 **[Join the discussion](https://github.com/suites-dev/suites/discussions/categories/q-a)** 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.
[↗️ Migrating from Automock Guide](https://suites.dev/docs/migration-guides/from-automock)
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](LICENSE).
