본문 바로가기
Node js/Nest js

Nest js Test Container 구성!! feat. Mysql

by Bill Lab 2024. 11. 23.
728x90

최근 대세(?)로 부각한, 테스트 주도 개발을 하기위해서는,,

테스트 코드 작성이 필수 이다. 

(단위테스트, 통합테스트, e2e 테스트 등)

 

다만, 여기서 테스트 수행 시 DB가 항상 접속이 되어있어야 할까?는 다소 의문스러운 영역이긴하다

왜? 독립적인 구성에서의 테스트가 이루어 져야하기 때문이다.

예를 들면, Kafka 를 도입해서 사용중인데, Kafka 가 항상 있어야만 테스트를 돌릴수 있는가?

라는 상황이면, github action 내에서 push 시점에서 테스트코드를 돌리기가 힘들것이다.

(물론, 배포 후 cypress 등을 이용한 e2e테스트는 다를 수 있다.)

 

결론적으로는 B/E 단에서 독립적인 테스트 환경이 보장되냐 안되냐가 중요한 것이다.

(서론이 다소 길었다.)

 

자, 그럼 독립적인 환경보장을 하기위해서는?

어떻게 해야할까??

 

Test Container 를 사용하는 것이다.

사용법은 의외로 간단하다.

 

Nest js 기반, Mysql, ORM 으로는 typeORM 을 사용하고 있다고 가정하자,

(Nest 사용법은 필요한 내용은 함께 담았다)

 

첫번째로 

npm install --save @nestjs/typeorm typeorm mysql2

typeORM 기반의 mysql 부터 설치해주자(이미 설치되어있으면 패스~)

https://docs.nestjs.com/techniques/database

 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Rea

docs.nestjs.com

 

 

두번째로

npm install --save-dev testcontainers @testcontainers/mysql

Test Container 를 설치하는 것이다!!

(주의! dev 용 dependency 로 잡아야 한다. 왜? 실 운영에 참조되는 라이브러리가 아니니깐!)

 

세번째로는 nestjs config 를 고민해볼 수 있다.

(일단 설치해보자)

npm install --save @nestjs/config

 

DB config 다시 확인해주고~!

(이미 DB connection 이 되는 소스이면 이단계 패스~)

export interface DatabaseConfig {
  host: string;
  port: number;
  database: string;
  username: string;
  password: string;
  logging: boolean;
}

export const dbConfig = () => ({
  database: {
    host: process.env.DB_HOST || "localhost",
    port: process.env.DB_PORT || 3306,
    database: process.env.DB_DATABASE || "test",
    username: process.env.DB_USERNAME || "root",
    password: process.env.DB_PASSWORD || "1234",
    logging: process.env.DB_LOGGING_ENABLED == "true" || false,
  } as DatabaseConfig,
});

 

Database Module 도 아래와 같이 수정해주자!

(typeORM setup 부분)

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { DatabaseConfig, dbConfig } from './database.config';

@Module({
  imports: [
    TypeOrmModule.forRootAsync({
      imports: [
        ConfigModule.forRoot({
          load: [dbConfig],
          envFilePath: '.env.dev',
        }),
      ],
      useFactory: (configService: ConfigService) => ({
        type: 'mysql',
        ...configService.get<DatabaseConfig>('database'),
        synchronize: false,
        autoLoadEntities: true,
        relationLoadStrategy: 'join',
      }),
      inject: [ConfigService],
    }),
  ],
  controllers: [],
  providers: [],
})
export class DatabaseModule {}

 

이제 typeORM 기반 entity도 추가하자

import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity({
  name: 'test',
})
export class TestEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;
}

 

 

repository 도 추가를 해야겠지?

import { TestEntity } from './entities/Test.entity';
import { Inject, Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';

@Injectable()
export class TestRepository {
  constructor(
    @Inject('TEST_REPOSITORY')
    private testRepository: Repository<TestEntity>,
  ) {}

  async findAll(): Promise<TestEntity[]> {
    return this.testRepository.find();
  }
}

 

package.json 도 수정을...

//아랫부분만 추가해보자!
"globalSetup": "./test/it/setup.ts",
"globalTeardown": "./test/it/testcode.ts",

 

테스트 코드를 작성해보자!

 

 

그럼 다음 테스트 실행도 추가해서 실행 실행하면!!  끝!

"test:it": "jest --config ./test/it/it.jest.json"

yarn test:it
728x90