mongodb-memory-server 도입기

백엔드·2023년 6월 17일
0

MongoDB

목록 보기
6/9

문제점

일부 기능의 테스트를 수행하기 위해서는 미리 생성되어야 하는 데이터 양이 상당히 많았습니다. 매번 테스트를 실행할 때마다 데이터를 수동으로 생성하는 것은 번거로웠기 때문에, 대신 Test DB에 데이터들을 만들어 놓고 테스트 시 해당 데이터를 사용하여 테스트를 수행하는 방식으로 대체했습니다.

기존의 CI (Continuous Integration) 과정에서 여러 개의 테스트가 동시에 실행될 때, 테스트 간의 상호작용으로 인해 문제가 발생하였습니다. 특히 테스트 데이터베이스의 공유 자원을 변경하는 테스트가 동시에 실행될 경우, 다른 테스트가 그 영향을 받아 테스트가 간헐적으로 실패하는 이슈가 발생하였습니다.

동시에 실행되는 테스트 간 상호작용: 여러 개의 테스트가 동시에 실행되면서 테스트 간에 상호작용이 발생했습니다. 예를 들어, 테스트 A에서 수정에 대한 테스트를 위해 공유 자원을 변경하였고 동시에 실행 중인 테스트 B에서 조회에 대한 테스트를 수행합니다.

예상치 못한 결과 발생: 테스트 A에서 변경한 공유 자원을 테스트 B에서 사용하는 경우, 해당 자원은 이미 수정되었기 때문에 테스트 B에서는 예상한 결과값이 아닌 실패하는 결과가 발생하였습니다. 이로 인해 테스트의 신뢰성이 떨어지는 문제가 있었습니다.

이러한 문제들로 인해 테스트 간의 독립성이 보장되지 않았고, CI 과정에서 예상치 못한 오류가 발생하여 안정적인 테스트 환경을 구축하는 데 어려움을 겪었습니다. 따라서 이 문제를 해결하기 위해 새로운 접근 방법을 도입하게 되었습니다.

해결 방안

해당 이슈를 해결하기 위해 mongodb-memory-server를 사용하여 in-memory 기반의 테스트 데이터베이스를 구축하여 테스트 간 독립성을 보장하고자 하였습니다.

mongodb-memory-server

  • mongodb-memory-server는 MongoDB의 in-memory 버전으로, 실제 MongoDB 데이터베이스를 메모리 내에 구축하여 테스트 용도로 사용할 수 있게 해줍니다. 이를 사용함으로써 실제 데이터베이스와 분리되어 독립적인 테스트 환경을 구축할 수 있습니다.

  • 각 테스트는 mongodb-memory-server를 통해 새로운 인스턴스를 생성하여 독립적인 데이터베이스 환경을 갖게 됩니다. 따라서 다른 테스트에 의해 영향을 받지 않고 각각의 테스트는 독립적으로 실행될 수 있습니다.

  • 테스트에 사용되는 in-memory 데이터베이스는 실제 MongoDB와 완전히 분리되어 있습니다. 따라서 테스트에서 데이터를 생성, 수정 또는 삭제해도 실제 데이터베이스에는 영향을 미치지 않습니다.

작업 진행



📂 e2e test architecture


👨‍💻 코드 예시

beforeAll(async () => {
  permissionModule = await Test.createTestingModule({
    imports: [
      rootMongooseTestModule(),
      WinstonModule.forRootAsync({ useClass: WinstonConfigService }),
      ...필요한 module import
    ],
  })
    .overrideGuard(AuthGuard)
    .useValue({ canActivate: () => true })
    .compile();

  app = permissionModule.createNestApplication();
  app.useGlobalInterceptors(new TransformInterceptor());

 ... 필요한 model 의존성 주입

  await app.init();
});
describe("Permission Controller", () => {
  describe("POST: 'permissions", () => {
    beforeAll(async () => {
      const mockDependency = dependencyFactory.createDependency();
      const dependency = await dependencyModel.create(
        mockDependency,
      );
      dependencyId = dependency._id.toString();
    }); // beforeAll을 통해 Test Item을 생성하기 위해 필요한 부모인 dependency 생성

    it("Should create a test Item", async () => {
      const mockTestItem = testFactory.createTest(dependencyId);

      const response = await request(app.getHttpServer())
        .post("/test")
        .send(mockTest)
        .expect(201);
    });
  });
});

결과

mongodb-memory-server를 통해 구축한 in-memory 기반의 테스트 데이터베이스를 사용함으로써 테스트 간의 독립성이 보장되어, 예상치 못한 상호작용으로 인한 문제가 사라졌습니다. 이를 통해 안정적인 테스트 환경을 구축하였고, CI 과정에서도 신뢰성 높은 테스트를 실행할 수 있게 되었습니다.

profile
백엔드 개발자

0개의 댓글