|
| 1 | +# Suites Examples |
| 2 | + |
| 3 | +Real-world examples demonstrating [Suites](https://suites.dev) integration with popular dependency injection frameworks and test runners. |
| 4 | + |
| 5 | +Each example showcases [solitary](https://suites.dev/docs/api-reference/testbed-solitary) and [sociable](https://suites.dev/docs/api-reference/testbed-sociable) testing patterns using the same user management domain model. |
| 6 | + |
| 7 | +If you are new to Suites, check out the [Getting Started](https://suites.dev/docs/getting-started) guide. |
| 8 | + |
| 9 | +## Examples |
| 10 | + |
| 11 | +| Example | DI Framework | Test Runner | Use When | |
| 12 | +| ---------------------------------------------- | ------------ | ----------- | ------------------------------------------------- | |
| 13 | +| [nestjs-jest](./nestjs-jest) | NestJS | Jest | NestJS with Jest | |
| 14 | +| [nestjs-vitest](./nestjs-vitest) | NestJS | Vitest | NestJS with Vitest | |
| 15 | +| [nestjs-sinon](./nestjs-sinon) | NestJS | Sinon | NestJS with Sinon/Mocha | |
| 16 | +| [inversify-jest](./inversify-jest) | InversifyJS | Jest | InversifyJS with Jest | |
| 17 | +| [inversify-vitest](./inversify-vitest) | InversifyJS | Vitest | InversifyJS with Vitest | |
| 18 | +| [inversify-sinon](./inversify-sinon) | InversifyJS | Sinon | InversifyJS with Sinon/Mocha | |
| 19 | +| [advanced-mock-config](./advanced-mock-config) | NestJS | Jest | Advanced `.mock().final()` and `.impl()` patterns | |
| 20 | + |
| 21 | +## Quick Start |
| 22 | + |
| 23 | +```bash |
| 24 | +# Clone and run any example |
| 25 | +cd nestjs-jest |
| 26 | +pnpm install |
| 27 | +pnpm test |
| 28 | +``` |
| 29 | + |
| 30 | +All tests should pass immediately, demonstrating both testing strategies. |
| 31 | + |
| 32 | +## Testing Strategies |
| 33 | + |
| 34 | +Each example demonstrates two approaches: |
| 35 | + |
| 36 | +### Solitary Unit Tests |
| 37 | + |
| 38 | +```typescript |
| 39 | +const { unit, unitRef } = await TestBed.solitary(UserService).compile(); |
| 40 | +``` |
| 41 | + |
| 42 | +Test one class in complete isolation. All dependencies are replaced with test doubles. |
| 43 | + |
| 44 | +**When to use:** |
| 45 | + |
| 46 | +- Testing component logic in isolation |
| 47 | +- Controlling all inputs for predictable results |
| 48 | + |
| 49 | +**Trade-off:** Does not verify interactions between components |
| 50 | + |
| 51 | +### Sociable Unit Tests |
| 52 | + |
| 53 | +```typescript |
| 54 | +const { unit, unitRef } = await TestBed.sociable(UserService) |
| 55 | + .expose(UserValidator) // Use real validator |
| 56 | + .expose(UserRepository) // Use real repository |
| 57 | + .compile(); |
| 58 | +``` |
| 59 | + |
| 60 | +Test multiple classes together with their real collaborators. External I/O (databases, APIs, file systems) is replaced with test doubles to keep tests fast. |
| 61 | + |
| 62 | +**When to use:** |
| 63 | + |
| 64 | +- Verifying components work together correctly |
| 65 | +- Testing interactions between business logic components |
| 66 | + |
| 67 | +**Trade-off:** Slower execution, multiple failure points |
| 68 | + |
| 69 | +Both strategies are unit tests - they keep external I/O mocked and remain fast. Use both together for comprehensive coverage. |
| 70 | + |
| 71 | +## What Each Example Demonstrates |
| 72 | + |
| 73 | +- **Solitary unit tests** - Test one class in complete isolation with all dependencies mocked |
| 74 | +- **Sociable unit tests** - Test multiple classes together with real collaborators, external I/O mocked |
| 75 | +- **Type-safe mocking** - Full TypeScript support without manual setup |
| 76 | +- **Zero boilerplate** - No test module configuration required |
| 77 | + |
| 78 | +## Common Use Case |
| 79 | + |
| 80 | +All examples implement the same user management service with three key components: |
| 81 | + |
| 82 | +```mermaid |
| 83 | +graph LR |
| 84 | + UserService --> UserValidator |
| 85 | + UserService --> UserRepository |
| 86 | + UserRepository --> DATABASE_TOKEN |
| 87 | +``` |
| 88 | + |
| 89 | +- **UserService** - Business logic layer with validation and persistence |
| 90 | +- **UserValidator** - Email validation (no dependencies) |
| 91 | +- **UserRepository** - Data access layer (depends on database token) |
| 92 | + |
| 93 | +This consistent domain model makes it easy to compare different framework and test runner combinations. |
| 94 | + |
| 95 | +## Repository Structure |
| 96 | + |
| 97 | +``` |
| 98 | +examples/ |
| 99 | +├── nestjs-jest/ # NestJS with Jest |
| 100 | +├── nestjs-vitest/ # NestJS with Vitest |
| 101 | +├── nestjs-sinon/ # NestJS with Sinon |
| 102 | +├── inversify-jest/ # InversifyJS with Jest |
| 103 | +├── inversify-vitest/ # InversifyJS with Vitest |
| 104 | +├── inversify-sinon/ # InversifyJS with Sinon |
| 105 | +└── advanced-mock-config/ # Advanced .mock().final() and .impl() patterns |
| 106 | +``` |
| 107 | + |
| 108 | +Each example contains two directories: |
| 109 | + |
| 110 | +**`src/`** - Application code being tested: |
| 111 | + |
| 112 | +- `types.ts` - Domain types and interfaces |
| 113 | +- `user.service.ts` - Business logic layer |
| 114 | +- `user.validator.ts` - Validation logic |
| 115 | +- `user.repository.ts` - Data access layer |
| 116 | + |
| 117 | +**`tests/`** - Tests demonstrating Suites usage: |
| 118 | + |
| 119 | +- `user.solitary.spec.ts` - Solitary unit tests (all dependencies mocked) |
| 120 | +- `user.sociable.spec.ts` - Sociable unit tests (real collaborators, external I/O mocked) |
| 121 | + |
| 122 | +## Prerequisites |
| 123 | + |
| 124 | +- Node.js 18 or higher |
| 125 | +- pnpm installed globally |
| 126 | +- Basic understanding of TypeScript and dependency injection |
| 127 | + |
| 128 | +## Troubleshooting |
| 129 | + |
| 130 | +### Tests fail after install |
| 131 | + |
| 132 | +1. Check Node.js version: `node --version` (requires 18+) |
| 133 | +2. Check pnpm: `pnpm --version` |
| 134 | +3. Clear and reinstall: `rm -rf node_modules && pnpm install` |
| 135 | +4. Verify working directory is the example directory, not repository root |
| 136 | + |
| 137 | +### "reflect-metadata" errors (InversifyJS examples) |
| 138 | + |
| 139 | +InversifyJS requires decorator metadata. Configuration is already set in `tsconfig.json` and imports. If errors occur, verify: |
| 140 | + |
| 141 | +- `experimentalDecorators: true` in tsconfig.json |
| 142 | +- `emitDecoratorMetadata: true` in tsconfig.json |
| 143 | +- `import 'reflect-metadata'` at top of test files |
| 144 | + |
| 145 | +### Sinon tests show different output format |
| 146 | + |
| 147 | +Sinon uses Mocha test runner, which formats output differently than Jest/Vitest. All examples show 6 passing tests. |
| 148 | + |
| 149 | +### "Module not found" errors |
| 150 | + |
| 151 | +Run `pnpm install` in the specific example directory. Each example has standalone dependencies. |
| 152 | + |
| 153 | +## Learn More |
| 154 | + |
| 155 | +- [Suites Documentation](https://suites.dev) |
| 156 | +- [Testing Strategies Guide](https://suites.dev/docs/testing-strategies) |
| 157 | +- [NestJS Integration](https://suites.dev/docs/nestjs) |
| 158 | +- [InversifyJS Integration](https://suites.dev/docs/inversify) |
0 commit comments