Tran Nhat Sang logo
3-co-che-test-cua-ung-dung-nestjs

So sánh giữa 3 cơ chế test trong ứng dụng NestJS

Ở bài viết trước mình có chia sẻ về cơ chế NestJS testing cơ bản, ngày hôm nay mình muốn chia sẻ chi tiết hơn và so sánh 3 cơ chế test trong ứng dụng NestJS bao gồm Unitest, Intergration test, End to End test. Vậy 3 cơ chế này khác nhau như thế nào ? Và khi nào cần dùng trong dự án. Theo dõi bài viết bên dưới của mình nhé

1. Unit Test

  • Mục tiêu: Kiểm tra logic của từng thành phần riêng lẻ (class, function, module).
  • Phạm vi: Chỉ kiểm tra một đơn vị code cụ thể và mock tất cả các dependencies.
  • Đặc điểm:
    • Tập trung vào logic nội bộ của thành phần.
    • Nhanh, dễ viết, và không phụ thuộc vào môi trường bên ngoài.
    • Sử dụng mock để giả lập dependencies.
  • Ví dụ: Kiểm tra UsersService hoạt động đúng khi sử dụng repository đã được mock.

Code ví dụ:


describe('UsersService', () => {
  let service: UsersService;
  let mockRepository: Partial<UsersRepository>;

  beforeEach(() => {
    mockRepository = {
      findById: jest.fn((id) => `Mocked User ${id}`),
    };

    service = new UsersService(mockRepository as UsersRepository);
  });

  it('should return user by ID', () => {
    const result = service.getUserById(1);
    expect(result).toBe('Mocked User 1');
    expect(mockRepository.findById).toHaveBeenCalledWith(1);
  });
});



2. Integration Test

  • Mục tiêu: Kiểm tra sự tương tác giữa các thành phần trong module (controller, service, repository).
  • Phạm vi: Kiểm tra nhiều thành phần cùng hoạt động, nhưng thường không bao gồm kết nối cơ sở dữ liệu thực.
  • Đặc điểm:
    • Không mock tất cả dependencies, mà sử dụng các phiên bản thực.
    • Đảm bảo các thành phần tích hợp đúng cách (ví dụ: UsersService gọi đúng repository và controller trả về đúng format).
  • Ví dụ: Kiểm tra UsersController trả về đúng dữ liệu khi gọi UsersService.

Code ví dụ:


describe('UsersController', () => {
  let controller: UsersController;
  let service: UsersService;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      controllers: [UsersController],
      providers: [UsersService, UsersRepository],
    }).compile();

    controller = module.get<UsersController>(UsersController);
    service = module.get<UsersService>(UsersService);
  });

  it('should return user by ID', async () => {
    jest.spyOn(service, 'getUserById').mockResolvedValue('User 1');
    const result = await controller.getUserById(1);
    expect(result).toBe('User 1');
  });
});


3. End-to-End (e2e) Test

  • Mục tiêu: Kiểm tra toàn bộ flow của ứng dụng từ client đến backend, bao gồm cả cơ sở dữ liệu thực.
  • Phạm vi: Kiểm tra hệ thống như một ứng dụng hoàn chỉnh.
  • Đặc điểm:
    • Không mock bất kỳ thành phần nào.
    • Yêu cầu môi trường thực tế, ví dụ: server chạy và kết nối cơ sở dữ liệu.
    • Chậm hơn nhưng đảm bảo rằng toàn bộ ứng dụng hoạt động như mong đợi.
  • Ví dụ: Kiểm tra API /users/:id trả về đúng dữ liệu từ database.

Code ví dụ:


import * as request from 'supertest';

describe('Users (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [UsersModule],
    }).compile();

    app = module.createNestApplication();
    await app.init();
  });

  it('GET /users/:id', async () => {
    const response = await request(app.getHttpServer())
      .get('/users/1')
      .expect(200);

    expect(response.body).toEqual({ id: 1, name: 'User 1' });
  });

  afterAll(async () => {
    await app.close();
  });
});


So sánh

Tiêu chíUnit TestIntegration TestEnd-to-End Test
Mục tiêuKiểm tra logic của từng thành phầnKiểm tra sự tương tác giữa các thành phầnKiểm tra toàn bộ ứng dụng
Phạm viRất nhỏ (một class hoặc function)Module hoặc nhóm componentHệ thống hoàn chỉnh
DependenciesĐược mockMột số thực, một số mockSử dụng thực tế
Tốc độNhanhTrung bìnhChậm
Độ phức tạpThấpTrung bìnhCao
Khi nào sử dụng?Để kiểm tra logic cụ thể và nhanh chóngKhi muốn kiểm tra tích hợp giữa các thành phầnKhi kiểm tra toàn bộ hệ thống

Khi nào nên sử dụng loại test nào của 3 cơ chế test trong ứng dụng NestJS

  1. Unit Test:

    • Kiểm tra logic cụ thể (ví dụ: tính toán, xử lý dữ liệu).
    • Dùng thường xuyên vì chúng nhanh và dễ viết.
  2. Integration Test:

    • Đảm bảo rằng các thành phần hoạt động đúng khi tích hợp với nhau.
    • Thường viết cho controller để kiểm tra toàn bộ logic của module.
  3. End-to-End Test:

    • Kiểm tra hệ thống thực tế trước khi phát hành.
    • Dùng ít hơn vì chậm và cần môi trường phức tạp.

Tóm lại

  • Unit Tests: Kiểm tra nhanh, tập trung vào logic nhỏ.
  • Integration Tests: Đảm bảo các module hoạt động đúng với nhau.
  • e2e Tests: Đảm bảo hệ thống hoàn chỉnh không có lỗi lớn.

Sự kết hợp hợp lý cả 3 loại test sẽ đảm bảo chất lượng cao nhất cho ứng dụng của bạn.


Liên quan

[[NestJS Testing là gì ? 1 cách để đảm bảo ứng chạy hiệu quả]]

https://chatgpt.com/share/67775eed-5a40-8013-b24c-73a7c4bc13be

#nestjs #testing #backend

0 0 đánh giá
Đánh giá bài viết
Theo dõi
Thông báo của
guest
0 Góp ý
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất
Lên đầu trang
0
Rất thích suy nghĩ của bạn, hãy bình luận.x