04-05 00:32
Notice
Recent Posts
관리 메뉴

독산구너

불필요한 기능 무효화로 Jest 테스트 최적화 본문

NestJS

불필요한 기능 무효화로 Jest 테스트 최적화

독산구너 2024. 11. 28. 20:20

글의 목적

현재 개발중인 NestJS 프로젝트에서는 이메일로 전송된 코드를 입력해 로그인하도록 합니다. 이 기능의 테스트코드를 작성하면서 발생한 문제점과 해결방안을 써보고자 합니다. 이 글을 통해 Jest 테스트에서 꼭 필요하지 않은 특정 외부 서비스 의존성을 제거하는 방식을 알게됩니다.

 

문제점

이메일 전송 기능은 @nestjs-modules/mailer의 MailerService를 통해 구현됩니다.

export declare class MailerService {
    ...
    constructor(mailerOptions: MailerOptions, transportFactory: IMailerTransportFactory);
    ...
    verifyAllTransporters(): Promise<boolean>;
    sendMail(sendMailOptions: ISendMailOptions): Promise<SentMessageInfo>;
    addTransporter(transporterName: string, config: string | smtpTransport | smtpTransport.Options): string;
}

하지만 테스트 환경에서 실제 이메일을 보내는 것에는 문제점이 있습니다.

  1. 비용 발생: 테스트를 수행할 때마다 이메일 전송을 수행해야 하고, 이메일 전송으로 인한 비용을 발생시킬 수 있습니다.
  2. 시간 지연: 네트워크 요청으로 속도가 느려집니다.
  3. 의존성 문제: 이메일 서버가 비정상적이라면 로직의 성공 유무와 상관없이 테스트가 실패할 수 있습니다.
  4. 불필요한 작업: 이메일 전송은 테스트 주요 목적과 직접적인 관련이 없습니다.

 

해결방안

Mocking MailerService

: MailerService의 실제 동작을 Jest의 mock 기능으로 대체해서, 테스트중에 이메일 전송 로직이 실행되지 않도록 합니다.

 

beforeAll에서 사용해 MailerService를 사용하는 모든 테스트에서 mock을 사용하도록 했습니다.

beforeAll(async () => {
    const moduleRef: TestingModule = await Test.createTestingModule({
      imports: [AppModule], // 애플리케이션 모듈을 로드
    })
      // MailerService를 Mock으로 대체
      .overrideProvider(MailerService)
      .useValue({
        sendMail: jest.fn().mockResolvedValue(null), // Mock 메서드 정의
      })
      .compile();
}

 

관련된 모든 비지니스 로직 코드는 변경하지 않아도 되는것이 최고 장점입니다. 단순히 overrideProvider를 통해서 MailerService를 mock 객체로 대체합니다.

 

overrideProvider: Provider를 대체하기 위해 사용됩니다. 이때는 DI 내 MailerService provider를 대체합니다.

useValue: DI(Dependency Injection) 시스템에서 특정 Provider를 대체하기 위한 옵션입니다. 정적인 값이나 간단한 Mock 객체를 주입할 때 사용합니다. (서비스를 주입하거나 동적 값 생성을 위한 useClass, useFactory 등이 존재합니다)

mockResolvedValue: Jest에서 제공하는 메서드로, 비동기 함수(특히 Promise를 반환하는 함수)를 Mock 처리할 때 사용됩니다. Mock 함수가 호출될 때 자동으로 지정한 값을 성공적으로 반환하도록 설정합니다.

 

 

mock 사용을 통해 이메일 전송에 1초이상 소요되던 시간과 리소스를 줄일 수 있었고, 비지니스 로직 테스트에 더욱 집중할 수 있었습니다.

  1. 의존성 제거: 이메일 서버와의 연결을 제거하여 테스트가 독립적으로 실행되도록 합니다.
  2. 테스트 속도 향상
  3. 일관성 유지: 이메일 서버 상태와 무관하게 항상 일관된 테스트 결과를 얻을 수 있습니다.

 

Mock 사용을 통해

테스트 코드를 작성하면서, 서비스 내 기능을 조작하는 mock에 대한 안좋은 인식을 가지고 있었습니다. 그러면 충분히 테스트 하는게 아니지 않나? 라는 생각이었습니다.

하지만 테스트하고자 하는 기능에 집중하기 위해 부가적인 기능이나 리소스를 많이 사용하는 기능은 mock을 통해 무효화시키고 간단히 만들 수 있구나 라는 것을 느낄 수 있었습니다.

 

테스트 1개 당 확인하고자 하는 기능을 1개로 제한하는 연습을 하고 있습니다. 이 과정에서 mock이 유용하게 사용되고 있습니다. 재밌네요!

'NestJS' 카테고리의 다른 글

NestJS Guard, JWT 기반 권한 레벨 관리  (18) 2024.11.24
멀티테넌시 구조와 NestJS Typeorm 사용 구현  (0) 2024.11.20
NestJS Library 사용  (4) 2024.11.19