Nestjs에서 Jest를 이용해서 테스트를 작성할 때, 통합테스트를 하는 경우에 테스트를 할 때 너무 시간이 오래 걸렸습니다. 🙄
CI에서 통합테스트를 진행한다고 하면, 간단한 프로젝트인데도, 15분 가까이 걸려 테스트가 완료되기 까지 기다리는 경험을 최근에 했는데요,
통합테스트 속도와 관련된 문제는 다들 한번씩 경험 해보셨을 것 같습니다.
왜 그런지 살펴보고 저와 비슷한 고민을 하는 사람이 있나 살펴보던 도중 저와 비슷한 생각을 하신 분의 글을 발견했습니다.
Jest의 경우 테스트를 진행할 때, 파일 기반으로 테스를 진행하다보니, 통합테스트를 모듈별로 진행하도록 파일을 여러개 두는 경우에는 각각의 파일을 테스트할 때 마다, Application의 빌드와 초기화 과정을 거쳐야 합니다.
반면 Mocha 동작 방식은 테스트 파일을 모두 찾아서, 한번에 테스트를 컴파일 합니다. Application의 설정을 통합테스트 전역에서 적용한다면, Application 빌드와 초기화 를 시작과 끝에 한번만 하면 된다는 뜻입니다. 🥹
그래서 Jest가 아닌 Mocha를 이용해서 Nestjs Test를 진행해보도록 하겠습니다.
Jest의 경우, Test Framework라서, 내부에 Test Runner, Test Matcher, Test Mock이 다 있지만, Mocha는 Test Runner이기 때문에, Test Matcher, Test Mock을 직접 선택해서 조합해, 사용해야 합니다.
필자는 Test Matcher로는 Chai, Test Mock으로는 Sinon을 사용하겠습니다. 그리고 e2e test를 위해 supertest를 추가로 사용하겠습니다.
코드는 typescript로 작성되기 때문에, typescript를 위해서 @types/... 도 의존성을 추가해야 합니다.
npm i --save-dev @types/mocha mocha @types/chai chai @types/sinon sinon @types/supertest supertest
테스트 진행 시, 어떻게 테스트를 구성할지 설명(describe)하고, 테스트를 실행(it)할 수 있도록 하는 도구
Mocha - the fun, simple, flexible JavaScript test framework
해당 Test Runner를 통해서 실제 테스트를 만들고 수행할 수 있습니다.
describe('Test', () => {
it("Test Execute", () => {
// test 진행
}
})
.mocharc.json
파일에서 초기 설정이 가능테스트 진행 시, 테스트 된 값과 실제 예상 값이 같은지 비교하기 위한 도구
Chai는 비교를 위한 여러가지 인터페이스를 제공됩니다.
BDD 기반으로 이해하기 쉬운 테스트 코드를 작성할 수 있습니다.
expect(result).to.equals(expectUUID);
Chai Issue 중 Chai 5.0.0 이상 사용 시
TypeError: Unknown file extension ".ts" for /Users/me/git/myProj/test/app.test.ts
at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:160:9)
at defaultGetFormat (node:internal/modules/esm/get_format:203:36)
at defaultLoad (node:internal/modules/esm/load:143:22)
at async ModuleLoader.load (node:internal/modules/esm/loader:409:7)
at async ModuleLoader.moduleProvider (node:internal/modules/esm/loader:291:45)
at async link (node:internal/modules/esm/module_job:76:21)
이런 문제가 발생했다면 여기를 클릭하면 Trouble Shooting 내용을 확인할 수 있습니다. :)
실제 테스트 하고자 하는 대상 외의 대상을 Mocking할 수 있는 도구
Sinon은 함수나 객체를 모방할 수 있도록 하고, 호출 횟수나, 결과값도 조작할 수 있습니다.
createStub = sandbox.stub(repository, 'save');
createStub.callsFake(() =>
Promise.resolve({
id: expectUUID,
name: dto.name,
description: dto.description,
}),
);
E2E Test를 할 수 있도록, Endpoint 요청을 만들어서 보내고, 결과 값을 비교할 수 있도록 돕는 도구
Supertest를 이용하면, Endpoint를 이용해서 요청을 보내고 응답을 받아 이를 예상값과 비교할 수 있습니다.
it('GET /users', () => {
return request(app.getHttpServer()).get('/').expect(200);
});
자료를 많이 찾아보았는데 국내에서는 Mocha를 이용해서 테스트 코드를 직접 구현해 놓은 예시가 없었습니다.
해외 자료 예시는 있기는 했지만, 7년 전 자료이고, 관련 라이브러리 동작방식이 달라져서, 실제로 사용하기는 힘들어 보였습니다.
간단하게 사용방법을 확인할 수 있도록 예제를 미리 만들어두었습니다.
Mocha 사용이 필요하신 분들은 한번 확인해보셔도 좋을 것 같습니다. :)
Mocha 가 무엇인지에 대해 잘 알 수 있는 게시글이었습니다 ^^