Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ jobs:
- inversify-sinon
- inversify-vitest
- nestjs-jest
- nestjs-jest-drizzle
- nestjs-jest-mikroorm
- nestjs-jest-prisma
- nestjs-jest-typeorm
- nestjs-sinon
- nestjs-vitest
node-version:
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ If you are new to Suites, check out the [Getting Started](https://suites.dev/doc
| Example | DI Framework | Test Runner | Use When |
| ---------------------------------------------- | ------------ | ----------- | ------------------------------------------------- |
| [nestjs-jest](./nestjs-jest) | NestJS | Jest | NestJS with Jest |
| [nestjs-jest-drizzle](./nestjs-jest-drizzle) | NestJS | Jest | NestJS with Jest + Drizzle ORM |
| [nestjs-jest-prisma](./nestjs-jest-prisma) | NestJS | Jest | NestJS with Jest + Prisma ORM |
| [nestjs-jest-typeorm](./nestjs-jest-typeorm) | NestJS | Jest | NestJS with Jest + TypeORM |
| [nestjs-jest-mikroorm](./nestjs-jest-mikroorm) | NestJS | Jest | NestJS with Jest + MikroORM |
| [nestjs-vitest](./nestjs-vitest) | NestJS | Vitest | NestJS with Vitest |
| [nestjs-sinon](./nestjs-sinon) | NestJS | Sinon | NestJS with Sinon/Mocha |
| [inversify-jest](./inversify-jest) | InversifyJS | Jest | InversifyJS with Jest |
Expand Down Expand Up @@ -97,6 +101,10 @@ This consistent domain model makes it easy to compare different framework and te
```
examples/
├── nestjs-jest/ # NestJS with Jest
├── nestjs-jest-drizzle/ # NestJS with Jest + Drizzle ORM
├── nestjs-jest-prisma/ # NestJS with Jest + Prisma ORM
├── nestjs-jest-typeorm/ # NestJS with Jest + TypeORM
├── nestjs-jest-mikroorm/ # NestJS with Jest + MikroORM
├── nestjs-vitest/ # NestJS with Vitest
├── nestjs-sinon/ # NestJS with Sinon
├── inversify-jest/ # InversifyJS with Jest
Expand Down
1 change: 1 addition & 0 deletions advanced-mock-config/tests/user.sociable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,4 @@ describe('User Service Unit Spec (Sociable Tests)', () => {
* - Best for: testing how real code handles various external responses
*/


1 change: 1 addition & 0 deletions advanced-mock-config/tests/user.solitary.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,4 @@ describe("User Service Unit Spec (Solitary Tests)", () => {
* - Use for: flexible defaults with per-test overrides
*/


1 change: 1 addition & 0 deletions inversify-jest/tests/user.sociable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ describe('User Service Unit Spec (Sociable Tests)', () => {
});
});


1 change: 1 addition & 0 deletions inversify-jest/tests/user.solitary.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,4 @@ describe('User Service Unit Spec (Solitary Tests)', () => {
});
});


1 change: 1 addition & 0 deletions inversify-sinon/tests/user.sociable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,4 @@ describe('User Service Unit Spec (Sociable Tests)', () => {
});
});


1 change: 1 addition & 0 deletions inversify-sinon/tests/user.solitary.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,4 @@ describe('User Service Unit Spec (Solitary Tests)', () => {
});
});


1 change: 1 addition & 0 deletions inversify-vitest/tests/user.sociable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ describe('User Service Unit Spec (Sociable Tests)', () => {
});
});


1 change: 1 addition & 0 deletions inversify-vitest/tests/user.solitary.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,4 @@ describe('User Service Unit Spec (Solitary Tests)', () => {
});
});


120 changes: 120 additions & 0 deletions nestjs-jest-drizzle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Suites + NestJS + Jest + Drizzle

Simple user management example demonstrating [Suites](https://suites.dev) with NestJS, Jest, and Drizzle ORM.

## Prerequisites

- Node.js 18 or higher
- pnpm installed globally

## What This Demonstrates

- ✅ **Solitary unit tests** - Test UserService in complete isolation
- ✅ **Sociable unit tests** - Test components together with real validation, mocked I/O
- ✅ **Token injection** - DATABASE_TOKEN as external boundary
- ✅ **Class injection** - UserValidator and UserRepository
- ✅ **Drizzle ORM integration** - Type-safe schema definitions with Drizzle

## Running the Example

```bash
pnpm install
pnpm test
```

All tests should pass, demonstrating both solitary and sociable testing strategies.

## Project Structure

**`src/`** - Application code being tested:

```
src/
├── types.ts # User types and interfaces
├── schema.ts # Drizzle schema definitions
├── user.validator.ts # Validation logic (no dependencies)
├── user.repository.ts # Data access (token injection)
└── user.service.ts # Business logic (class injections)
```

**`tests/`** - Tests demonstrating Suites usage:

```
tests/
├── user.solitary.spec.ts # Solitary unit tests (all dependencies mocked)
└── user.sociable.spec.ts # Sociable unit tests (real collaborators)
```

## Key Patterns

### Solitary Unit Tests

Tests one class in complete isolation. All dependencies are mocked.

```typescript
const { unit, unitRef } = await TestBed.solitary(UserService).compile();
const repository: Mocked<UserRepository> = unitRef.get(UserRepository);
repository.exists.mockResolvedValue(false);
```

### Sociable Unit Tests

Tests multiple classes together with real collaborators. External I/O remains mocked.

```typescript
const { unit, unitRef } = await TestBed.sociable(UserService)
.expose(UserValidator)
.expose(UserRepository)
.compile();
const database: Mocked<Database> = unitRef.get(DATABASE_TOKEN);
```

## Drizzle ORM Integration

This example uses Drizzle ORM for type-safe database schema definitions:

```typescript
import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core';

export const users = sqliteTable('users', {
id: integer('id').primaryKey(),
email: text('email').notNull().unique(),
name: text('name').notNull(),
isActive: integer('is_active', { mode: 'boolean' }).notNull().default(true)
});
```

Types are inferred from the schema:

```typescript
import { InferSelectModel, InferInsertModel } from 'drizzle-orm';
export type User = InferSelectModel<typeof users>;
export type CreateUserDto = InferInsertModel<typeof users>;
```

## Comparing Testing Strategies

**When to use Solitary:**
- Testing component logic in isolation
- Controlling all inputs for predictable results
- Dependencies are slow or complex to set up

**When to use Sociable:**
- Verifying components work together correctly
- Testing interactions between business logic components
- Dependencies are fast

## Related Examples

- [nestjs-jest](../nestjs-jest) - NestJS with Jest (no ORM)
- [nestjs-vitest](../nestjs-vitest) - Same framework with Vitest (faster execution)
- [nestjs-sinon](../nestjs-sinon) - Same framework with Sinon/Mocha

## Learn More

- [Suites Documentation](https://suites.dev)
- [NestJS Integration](https://suites.dev/docs/nestjs)
- [Testing Strategies](https://suites.dev/docs/testing-strategies)
- [Drizzle ORM Documentation](https://orm.drizzle.team)


3 changes: 3 additions & 0 deletions nestjs-jest-drizzle/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/// <reference types="@suites/doubles.jest/unit" />


14 changes: 14 additions & 0 deletions nestjs-jest-drizzle/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
testEnvironment: 'node',
testRegex: 'tests/.*\\.spec\\.ts$',
transform: {
'^.+\\.ts$': ['ts-jest', { isolatedModules: true }]
},
collectCoverageFrom: [
'src/**/*.ts',
'!src/types.ts',
'!src/schema.ts'
]
};


34 changes: 34 additions & 0 deletions nestjs-jest-drizzle/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "nestjs-jest-drizzle-example",
"version": "0.0.0",
"private": true,
"description": "Suites NestJS + Jest + Drizzle Example",
"scripts": {
"test": "tsc --noEmit && jest",
"start": "ts-node src/main.ts",
"build": "tsc"
},
"dependencies": {
"@nestjs/common": "^10.4.15",
"@nestjs/core": "^10.4.15",
"@nestjs/platform-express": "^10.4.15",
"better-sqlite3": "^11.3.0",
"drizzle-orm": "^0.29.0",
"reflect-metadata": "^0.2.2"
},
"devDependencies": {
"@suites/di.nestjs": "^3.0.1",
"@suites/doubles.jest": "^3.0.1",
"@suites/unit": "^3.0.1",
"@types/better-sqlite3": "^7.6.12",
"@types/jest": "^29.5.13",
"@types/node": "^20.14.0",
"jest": "^29.7.0",
"ts-jest": "^29.2.5",
"ts-node": "^10.9.2",
"typescript": "^5.7.2"
},
"packageManager": "[email protected]+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0"
}


Loading