Skip to content

✏️ TypeORM Datasource mock 만들기

baegyeong edited this page Nov 29, 2024 · 2 revisions
분야 작성자 작성일
BE 김민수 24년 11월 07일

어떤 문제인가요?

TypeORM 0.3버전으로 업데이트되면서 @Transactional 데코레이터가 지원이 중단되었다. 따라서 직접 트랜잭션에 대한 코드를 작성해야했다. 트랜잭션을 반영하는 코드는 2가지 방식이 있지만 이번 프로젝트에서 콜백 기반으로 동작하는 datasource의 트랜잭션을 사용하기로 했다. QueryRunner 방식을 사용하지 않은 이유는 에러가 발생되는 구간의 try-catch 문과 롤백 그리고 release 에 대한 코드를 작성해야하기 때문에 코드량이 많아지는 문제가 있다고 생각했기 때문에 datasource 방식을 채택했다.

 async increaseView(stockId: string) {
    await this.datasource.transaction(async (manager) => {
      const isExists = await manager.exists(Stock, { where: { id: stockId } });
      if (!isExists) {
        throw new NotFoundException('stock not found');
      }
      return await manager.increment(Stock, { id: stockId }, 'views', 1);
    });
  }

위 코드는 Service 단에서 특정 주식의 조회수를 증가시키는 로직을 datasource 트랜잭션 내부에 동작하도록 한 코드이다. 하지만 위 코드는 단위 테스트하기 어렵다. 왜냐하면 datasource 객체는 db-connection 이 유지해야하는 객체이기 때문에 단위 테스트를 하기 어려운 문제가 있다.

해당 문제가 왜 발생했나요?

해당 코드가 테스트하기 어려운 이유는 2가지가 있다.

  • 비즈니스 로직과 관심사 분리가 제대로 되지 않음
  • datasource 가 DB에 연결되지 않으면 예외가 발생

문제를 어떻게 해결했나요?

위 문제에서 비즈니스 로직과 관심사 분리가 제대로 되면 위 문제를 쉽게 해결할 수 있다. 이때 생각한 방법이 repository 단을 두거나, 커스텀 데코레이터를 만드는 것이다. 하지만 첫번째 방법은 DB에 작업을 수행하기 위해 entityManagerrepository 의 메소드에 파라미터로 계속 전달해야하는 문제가 있고, 두번째 방법은 시간이 오래걸려 제한된 시간동안 다른 기능 구현에 지장이 생길 수 있는 위험이 있다. 결국 첫 번째 문제보다는 두 번째 문제를 해결하면 된다고 생각하게 되었다.

Datasource mock 만들기

// DataSourceMock을 만드는 함수, managerMock을 전달받는다.
function createDataSourceMock(
  managerMock: Partial<EntityManager>,
): Partial<DataSource> {
  return {
    transaction: jest.fn().mockImplementation(async (work) => {
      return work(managerMock);
    }),
  };
}

const managerMock = {
  exists: jest.fn().mockResolvedValue(false),
  save: jest.fn().mockResolvedValue(registerRequest),
};
const dataSource = createDataSourceMock(managerMock);
const userService = new UserService(dataSource as DataSource);

위 코드는 Datasource mock 을 만든 후 서비스 객체에 주입하는 코드로 manager 가 수행할 함수를 mock 으로 변형시킨 managerMock 을 받는다.

이후 datasourcetransaction 함수를 jest.fn().mockImplementation 으로 콜백 함수에 전달되는 manager 를 미리 선언한 mock 객체를 전달하여 동작하도록 코드를 구현했다.

위 방식을 통해서 단위 테스트를 작성할 수 있었다.

🐜 팀 개미

🏛️ 팀 문화

개발 위키

FE

BE

Infra

🗣️ 발표

📚 회의록

🔴 인터미션
🟠 1주차
🟡 2주차
🟢 3주차
🔵 4주차
🟣 5주차
🟤 6주차

💭 회고

🧑‍🤝‍🧑 멘토링

Clone this wiki locally