Suites
Suites - bu TypeScript dependency injection freymvorklari uchun open-source unit-testing freymvorki. U mock'larni qo'lda yaratish, ko'p konfiguratsiyali uzun test setup yozish yoki
Suites - bu TypeScript dependency injection freymvorklari uchun open-source unit-testing freymvorki. U mock'larni qo'lda yaratish, ko'p konfiguratsiyali uzun test setup yozish yoki type'siz test double'lar (mocks, stubs) bilan ishlashga muqobil sifatida ishlatiladi.
Suites runtime vaqtida NestJS servislaridan metadata'ni o'qiydi va barcha dependency'lar uchun to'liq typed mock'larni avtomatik yaratadi.
Bu boilerplate mock setup'ni yo'qotadi va type-safe testlarni ta'minlaydi. Suites'ni Test.createTestingModule() bilan birga ishlatish mumkin bo'lsa-da, u ayniqsa focused unit testing'da kuchli.
Modul wiring, dekoratorlar, guard'lar va interceptor'larni tekshirishda Test.createTestingModule() dan foydalaning.
Avtomatik mock yaratish bilan tez unit testlar uchun esa Suites'dan foydalaning.
Modulga asoslangan testing haqida ko'proq ma'lumot uchun testing fundamentals bobini ko'ring.
Suites third-party paket bo'lib, NestJS core jamoasi tomonidan qo'llab-quvvatlanmaydi. Muammolarni mos repository ga yuboring.
Boshlash
Ushbu qo'llanma Suites yordamida NestJS servislarini test qilishni ko'rsatadi. U isolated testing (barcha dependency'lar mock qilingan) va sociable testing (tanlangan real implementatsiyalar ishlatiladigan) yondashuvlarini qamrab oladi.
Suites'ni o'rnatish
NestJS runtime dependency'lari o'rnatilganini tekshiring:
1$ npm install @nestjs/common @nestjs/core reflect-metadataSuites core, NestJS adapter va doubles adapter'ni o'rnating:
1$ npm install --save-dev @suites/unit @suites/di.nestjs @suites/doubles.jestDoubles adapter (@suites/doubles.jest) Jest'ning mocking imkoniyatlari ustiga wrapper beradi. U type-safe test double yaratadigan mock() va stub() funksiyalarini taqdim etadi.
Jest va TypeScript mavjudligiga ishonch hosil qiling:
1$ npm install --save-dev ts-jest @types/jest jest typescriptExpand if you're using Vitest
1$ npm install --save-dev @suites/unit @suites/di.nestjs @suites/doubles.vitestExpand if you're using Sinon
1$ npm install --save-dev @suites/unit @suites/di.nestjs @suites/doubles.sinonType definition'larni sozlash
Loyiha root'ida global.d.ts yarating:
1/// <reference types="@suites/doubles.jest/unit" />
2/// <reference types="@suites/di.nestjs/types" />Namuna service yaratish
Bu qo'llanmada ikki dependency'ga ega sodda UserService ishlatiladi:
1import { Injectable } from '@nestjs/common';
2
3@Injectable()
4export class UserRepository {
5 async findById(id: string): Promise<User | null> {
6 // Database query
7 }
8
9 async save(user: User): Promise<User> {
10 // Database save
11 }
12}1import { Injectable, NotFoundException } from '@nestjs/common';
2import { Logger } from '@nestjs/common';
3
4@Injectable()
5export class UserService {
6 constructor(
7 private repository: UserRepository,
8 private logger: Logger,
9 ) {}
10
11 async findById(id: string): Promise<User> {
12 const user = await this.repository.findById(id);
13 if (!user) {
14 throw new NotFoundException(`User ${id} not found`);
15 }
16 this.logger.log(`Found user ${id}`);
17 return user;
18 }
19
20 async create(email: string, name: string): Promise<User> {
21 const user = { id: generateId(), email, name };
22 await this.repository.save(user);
23 this.logger.log(`Created user ${user.id}`);
24 return user;
25 }
26}Unit test yozish
Barcha dependency'lar mock qilingan isolated testlar yaratish uchun TestBed.solitary() dan foydalaning:
1import { TestBed, type Mocked } from '@suites/unit';
2import { UserService } from './user.service';
3import { UserRepository } from './user.repository';
4import { Logger } from '@nestjs/common';
5
6describe('User Service Unit Spec', () => {
7 let userService: UserService;
8 let repository: Mocked<UserRepository>;
9 let logger: Mocked<Logger>;
10
11 beforeAll(async () => {
12 const { unit, unitRef } = await TestBed.solitary(UserService).compile();
13
14 userService = unit;
15 repository = unitRef.get(UserRepository);
16 logger = unitRef.get(Logger);
17 });
18
19 it('should find user by id', async () => {
20 const user = { id: '1', email: 'test@example.com', name: 'Test' };
21 repository.findById.mockResolvedValue(user);
22
23 const result = await userService.findById('1');
24
25 expect(result).toEqual(user);
26 expect(logger.log).toHaveBeenCalled();
27 });
28});TestBed.solitary() constructor'ni tahlil qilib, barcha dependency'lar uchun typed mock yaratadi.
Mocked<T> turi mock konfiguratsiyasi uchun IntelliSense qo'llab-quvvatlashini beradi.
Compile'dan oldin mock konfiguratsiyasi
Mock xatti-harakatini compile'dan oldin .mock().impl() orqali sozlang:
1import { TestBed } from '@suites/unit';
2import { UserService } from './user.service';
3import { UserRepository } from './user.repository';
4
5describe('User Service Unit Spec - pre-configured', () => {
6 let unit: UserService;
7 let repository: Mocked<UserRepository>;
8
9 beforeAll(async () => {
10 const { unit: underTest, unitRef } = await TestBed.solitary(UserService)
11 .mock(UserRepository)
12 .impl(stubFn => ({
13 findById: stubFn().mockResolvedValue({ id: '1', email: 'test@example.com', name: 'Test' })
14 }))
15 .compile();
16
17 repository = unitRef.get(UserRepository);
18 unit = underTest;
19 })
20
21 it('should find user with pre-configured mock', async () => {
22 const result = await unit.findById('1');
23
24 expect(repository.findById).toHaveBeenCalled();
25 expect(result.email).toBe('test@example.com');
26 });
27});stubFn parametri o'rnatilgan doubles adapter'ga mos keladi (Jest uchun jest.fn(), Vitest uchun vi.fn(), Sinon uchun sinon.stub()).
Real dependency'lar bilan testing
Muayyan dependency'lar uchun real implementatsiyalardan foydalanish uchun .expose() bilan TestBed.sociable() dan foydalaning:
1import { TestBed, Mocked } from '@suites/unit';
2import { UserService } from './user.service';
3import { UserRepository } from './user.repository';
4import { Logger } from '@nestjs/common';
5
6describe('UserService - with real logger', () => {
7 let userService: UserService;
8 let repository: Mocked<UserRepository>;
9
10 beforeAll(async () => {
11 const { unit, unitRef } = await TestBed.sociable(UserService)
12 .expose(Logger)
13 .compile();
14
15 userService = unit;
16 repository = unitRef.get(UserRepository);
17 });
18
19 it('should log when finding user', async () => {
20 const user = { id: '1', email: 'test@example.com' };
21 repository.findById.mockResolvedValue(user);
22
23 await userService.findById('1');
24
25 // Logger actually executes, no mock needed
26 });
27});.expose(Logger) Logger ni real implementatsiyasi bilan yaratadi, qolgan dependency'lar esa mock bo'lib qoladi.
Token-based dependency'lar
Suites custom injection token'larni (string yoki symbol) qo'llab-quvvatlaydi:
1import { Injectable, Inject } from '@nestjs/common';
2
3export const CONFIG_OPTIONS = 'CONFIG_OPTIONS';
4
5@Injectable()
6export class ConfigService {
7 constructor(
8 @Inject(CONFIG_OPTIONS) private options: { apiKey: string },
9 ) {}
10
11 getApiKey(): string {
12 return this.options.apiKey;
13 }
14}Token-based dependency'larga unitRef.get() orqali murojaat qiling:
1import { TestBed } from '@suites/unit';
2import { ConfigService, CONFIG_OPTIONS, ConfigOptions } from './config.service';
3
4describe('Config Service Unit Spec', () => {
5 let configService: ConfigService;
6 let options: ConfigOptions;
7
8 beforeAll(async () => {
9 const { unit, unitRef } = await TestBed.solitary(ConfigService).compile();
10 configService = unit;
11
12 options = unitRef.get<ConfigOptions>(CONFIG_OPTIONS);
13 });
14
15 it('should return api key', () => { ... });
16});mock() va stub() dan to'g'ridan-to'g'ri foydalanish
TestBed siz ishlatmoqchi bo'lmasangiz va to'g'ridan-to'g'ri nazorat kerak bo'lsa, doubles adapter paketi mock() va stub() funksiyalarini beradi:
1import { mock } from '@suites/unit';
2import { UserRepository } from './user.repository';
3
4describe('User Service Unit Spec', () => {
5 it('should work with direct mocks', async () => {
6 const repository = mock<UserRepository>();
7 const logger = mock<Logger>();
8
9 const service = new UserService(repository, logger);
10
11 // ...
12 });
13});mock() typed mock object yaratadi, stub() esa asosiy mocking kutubxonasini (bu misolda Jest) o'rab, mockResolvedValue() kabi metodlarni taqdim etadi.
Bu funksiyalar o'rnatilgan doubles adapter'dan (@suites/doubles.jest) keladi va u test freymvorkining native mocking imkoniyatlarini moslashtiradi.
mock() funksiyasi @golevelup/ts-jest dagi createMock ga muqobil hisoblanadi. Ikkalasi ham typed mock object yaratadi. createMock haqida ko'proq ma'lumot uchun testing fundamentals bobiga qarang.
Xulosa
Test.createTestingModule() dan quyidagilar uchun foydalaning:
- Validating module configuration and provider wiring
- Testing decorators, guards, interceptors, and pipes
- Verifying dependency injection across modules
- Testing full application context with middleware
Suites'dan quyidagilar uchun foydalaning:
- Fast unit tests focused on business logic
- Automatic mock generation for multiple dependencies
- Type-safe test doubles with IntelliSense
Testlarni maqsadiga qarab ajrating: alohida service xatti-harakatini tekshiradigan unit testlar uchun Suites'dan, modul konfiguratsiyasini tekshiradigan integration testlar uchun esa Test.createTestingModule() dan foydalaning.
Qo'shimcha ma'lumot:
- Suites Documentation
- Suites GitHub Repository
- NestJS Testing Documentation