An open API service indexing awesome lists of open source software.

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

Awesome Lists containing this project

README

          


Logo

Suites


A unit testing framework for TypeScript backends working with inversion of control and dependency injection


by @omermorad


license

npm downloads
npm downloads
Buy Me A Coffee


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

Buy Me A Coffee

## 📜 License

Suites is licensed under the [Apache License, Version 2.0](LICENSE).