So sánh giữa 3 cơ chế test trong ứng dụng NestJS
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ọiUsersService
.
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 Test | Integration Test | End-to-End Test |
---|---|---|---|
Mục tiêu | Kiểm tra logic của từng thành phần | Kiểm tra sự tương tác giữa các thành phần | Kiểm tra toàn bộ ứng dụng |
Phạm vi | Rất nhỏ (một class hoặc function) | Module hoặc nhóm component | Hệ thống hoàn chỉnh |
Dependencies | Được mock | Một số thực, một số mock | Sử dụng thực tế |
Tốc độ | Nhanh | Trung bình | Chậm |
Độ phức tạp | Thấp | Trung bình | Cao |
Khi nào sử dụng? | Để kiểm tra logic cụ thể và nhanh chóng | Khi muốn kiểm tra tích hợp giữa các thành phần | Khi kiểm tra toàn bộ hệ thống |
Khi nào nên sử dụng loại test nào?
-
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.
-
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.
-
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
All Rights Reserved