프로그래밍/Nest.js

Nest.js에서의 단위 테스트와 통합 테스트의 중요성

shimdh 2025. 3. 21. 09:04
728x90

소프트웨어 개발에서 테스트는 코드의 품질을 보장하고 버그를 조기에 발견하기 위해 필수적인 과정입니다. 특히 Nest.js와 같은 프레임워크에서는 두 가지 주요 유형의 테스트, 즉 단위 테스트통합 테스트를 통해 애플리케이션의 다양한 부분을 체계적으로 검증할 수 있습니다. 이러한 테스트는 개발 과정에서 발생할 수 있는 여러 문제를 사전에 예방하고, 최종 제품의 신뢰성을 높이는 데 기여합니다.

1. 단위 테스트 (Unit Testing)

단위 테스트는 개별 모듈이나 함수가 예상대로 작동하는지를 확인하는 데 초점을 맞추고 있습니다. 이 방법은 특정 기능이나 로직이 올바르게 구현되었는지 평가하는 데 중점을 두며, 각 구성 요소가 독립적으로 잘 작동하는지를 확인하는 것이 주된 목적입니다. 이를 통해 개발자는 코드의 작은 단위에서 발생할 수 있는 오류를 조기에 발견하고 수정할 수 있습니다.

단위 테스트의 목적

  • 각 구성 요소가 독립적으로 잘 작동하는지 확인
  • 코드의 작은 단위에서 발생할 수 있는 오류를 조기에 발견

단위 테스트 도구

  • Jest, Mocha 등과 같은 JavaScript 테스팅 프레임워크를 활용하여 효율적인 테스트 환경을 구축할 수 있습니다.

예시: 사용자 서비스(UserService) 단위 테스트

사용자 서비스는 사용자를 생성하고, 모든 사용자를 조회하는 기능을 제공합니다. 아래는 이 서비스의 코드입니다:

import { Injectable } from '@nestjs/common';

@Injectable()
export class UserService {
    private users = [];

    createUser(name: string) {
        const user = { id: Date.now(), name };
        this.users.push(user);
        return user;
    }

    findAll() {
        return this.users;
    }
}

이제 위 서비스를 위한 단위 테스트를 작성해보겠습니다. 이 테스트는 사용자가 제대로 생성되고, 모든 사용자가 올바르게 반환되는지를 검증합니다:

import { Test, TestingModule } from '@nestjs/testing';
import { UserService } from './user.service';

describe('UserService', () => {
    let service: UserService;

    beforeEach(async () => {
        const module: TestingModule = await Test.createTestingModule({
            providers: [UserService],
        }).compile();

        service = module.get<UserService>(UserService);
    });

    it('should create a user', () => {
        const user = service.createUser('John Doe');
        expect(user).toHaveProperty('id');
        expect(user.name).toEqual('John Doe');
    });

    it('should return all users', () => {
        service.createUser('Jane Doe');

        const users = service.findAll();

        expect(users.length).toBe(1);
        expect(users[0].name).toEqual('Jane Doe');
    });
});

2. 통합 테스트 (Integration Testing)

통합 테스트는 여러 구성 요소 간의 상호작용을 검사하여 시스템이 전체적으로 올바르게 작동하는지를 검증하는 과정입니다. 이 테스트는 데이터베이스 연결, API 호출 등을 포함한 실제 환경에서의 동작을 시뮬레이션하여, 서로 다른 모듈들이 함께 잘 작동하는지를 확인하는 데 중점을 둡니다. 이를 통해 개발자는 시스템의 전반적인 신뢰성을 높일 수 있습니다.

통합 테스트의 목적

  • 서로 다른 모듈들이 함께 잘 작동하는지 확인
  • 시스템의 전반적인 신뢰성을 높임

통합 테스트 도구

  • Supertest와 같은 HTTP 요청 라이브러리를 사용하여 실제 API 호출을 테스트할 수 있습니다.

예시: 사용자 API 엔드포인트 통합 테스트

사용자 API 엔드포인트에 대한 통합 테스트를 작성하겠습니다. 이 테스트는 사용자가 API를 통해 생성될 수 있는지를 검증합니다:

import request from 'supertest';
import { Test, TestingModule } from '@nestjs/testing';
import { AppModule } from '../src/app.module'; // 메인 앱 모듈 가져오기
import { INestApplication } from '@nestjs/common';

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

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

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

  it('/users (POST)', async () => {
      const response = await request(app.getHttpServer())
          .post('/users')
          .send({ name: 'John Doe' })
          .expect(201);

      expect(response.body.name).toEqual('John Doe');
      expect(response.body).toHaveProperty('id');
  });

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

결론

테스트는 Nest.js 애플리케이션 개발에서 중요한 역할을 합니다. 단위 테스트를 통해 개별 기능이 제대로 동작하는지를 검증하고, 통합 테스트로 여러 구성 요소 간의 상호작용과 전체적인 시스템 동작을 점검함으로써 신뢰성 높은 코드를 작성할 수 있습니다. 이러한 접근 방식을 통해 나중에 발생할 수 있는 문제들을 사전에 예방하고 유지보수를 용이하게 할 수 있습니다. 따라서, 개발자는 테스트를 통해 코드의 품질을 높이고, 사용자에게 더 나은 경험을 제공할 수 있는 기반을 마련할 수 있습니다.

728x90