[NestJS] | Testing , HTTP 상태 코드 정리

Hayeon LEE·2024년 3월 28일

NestJS

목록 보기
4/4
post-thumbnail

Testing을 위해 먼저 @nestjs/testing를 설치해야 한다.

  • 설치
npm i --save-dev @nestjs/testing

app.controller.ts라는 파일을 테스팅하고 싶다면 app.controller.spec.ts파일이 있어야 하는 것처럼 NestJs에서는 기본 규칙이다. 또한 jest는 보통 .spec.ts로 끝나는 파일들을 테스트 대상으로 인식하고 실행 수 있도록 설정되어 있다.

따라서 새로운 테스트 파일을 추가하면 Jest가 자동으로 해당 파일을 찾아 실행한다.

  "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  • test:watch:파일이 변경될 때마다 자동으로 테스트를 다시 실행한다.
  • test:cov : jest가 프로젝트의 코드 커버리지를 계산하고 보고서를 생성한다.이를 통해 어떤 부분이 테스트되지 않았는지를 파악할 수 있다.
  • test:debug : Jest를 디버깅 모드로 테스트
  • test:e2e : 전체 시스템을 테스트하는 것으로, 주로 페이지로 가면 특정 페이지가 나와야하는 경우 사용(사용자가 취할만한 액션들을 처음부터 끝까지 테스트)

Unit Testing

function 같은 하나의 유닛만을 테스트할 때 사용한다.또한, 코드의 각 부분이 예상대로 작동하는지 확인한다.

유닛 테스팅을 사용해서 MoviesService를 테스트해보자.

  • Jest에서 제공하는 각 훅

    • beforeEach(fn, timeout): 각각의 테스트 케이스가 실행되기 전에 실행한다.(데이터베이스 연결을 설정,테스트에 필요한 작업)
    • beforeAll(fn, timeout) : 모든 테스트 케이스가 실행되기 전에 한 번 실행한다.(테스트 환경의 전체 설정을 초기화)
    • afterEach(fn, timeout) : 각각의 테스트 케이스가 실행된 후에 실행한다. (clean-up 작업,, 데이터베이스 연결을 종료)
    • afterAll(fn, timeout) : 모든 테스트 케이스가 실행된 후에 한 번 실행한다.
  • describe(): 여러개의 it()을 하나의 Test 작업단위로 묶어주는 API이다.,하나의 작은 TestCase를 it()라고 한다면 describe()는 여러개의 TestCase를 하나의 그룹으로 묶어주는 역할을 한다.

  • beforeEach() : TestCase의 각 코드가 실행되기 전에 수행되어야 하는 로직을 넣는 API이다.반복되는 Logic을 넣을 때 사용된다.(테스트에 필요한 객체를 생성)

// 테스트하기 전에 실행
beforeEach(async () => {
  const module: TestingModule = await Test.createTestingModule({
    providers: [MoviesService],
  }).compile();

  service = module.get<MoviesService>(MoviesService);
});
  • expect(): 테스트에서 예상되는 결과를 지정해 테스트를 수행한다.
  // getOne 메서드가 올바른 영화 객체를 반환하는지 확인하는 테스트
  describe('getOne', () => {
    it('should return an movie', () => {
      service.create({
        // 테스트를 위해 가짜 데이터 생성
        title: 'Test Movie',
        genres: ['Movie'],
        year: 2000,
      });
      const movie = service.getOne(1);
      expect(movie).toBeDefined(); // getOne 메서드가 유효한 값을 반환했는지를 검증
      expect(movie.id).toEqual(1);
    });
  • toEqual(): 두 값이 서로 동일한지 확인한다.
  • toBeDefined():null과 undefined를 제외한 모든 값에 대해 true를 반환하고,값이 정의되었는지 확인한다.
  • toBeInstanceOf():값이 특정 클래스의 인스턴스인지 확인한다.
describe('getAll', () => {
  it('should return an array', () => {
    const result = service.getAll(); //  MoviesService의 getAll()의 결과가 배열 인스턴스인지 테스트
    expect(result).toBeInstanceOf(Array);
  });
});
describe('create', () => {
  it('should create a movie', () => {
    const beforeCreate = service.getAll().length;
    service.create({
      // movie 생성
      title: 'Test Movie',
      genres: ['Movie'],
      year: 2000,
    });
    const afterCreate = service.getAll().length;
    console.log(beforeCreate, afterCreate);
    expect(afterCreate).toBeGreaterThan(beforeCreate);
  });
});
  • toBeGreaterThan(): 값이 주어진 다른 값보다 큰지 확인한다. 주어진 값이 다른 값보다 크면 true,작으면 false반환

  • toBeLessThan();값이 주어진 다른 값보다 작은지 확인한다.

expect(afterDelete).toBeLessThan(beforeDeletes);

E2E Testing

개별 모듈 및 클래스에 초점을 맞추는 단위 테스트와 달리, e2e 테스트는 보다 종합적인 수준에서 클래스와 모듈의 상호 작용을 다룬다.
또한 Nest를 사용하면 Supertest 라이브러리를 사용하여 HTTP 요청을 쉽게 시뮬레이션할 수 있다.

request() 함수를 사용하여 Nest 앱에서 실행 중인 HTTP 서버에 대한 테스트 요청을 시뮬레이션한다. 이를 위해 request() 함수에 Nest 앱의 HTTP 서버를 가리키는 참조(app.getHttpServer())를 전달한다. 이렇게 하면 Supertest가 Nest 앱으로 요청을 보낼 수 있게 된다.
그 후에는 request().get('/cats')와 같이 사용하여 실제 HTTP 요청과 유사한 요청을 보낼 수 있다. 따라서 request(app.getHttpServer()).get('/cats')는 네트워크를 통해 /cats로 들어오는 실제 HTTP 요청과 동일한 요청을 Nest 앱으로 보내게 된다.

E2E Testing 공식 문서

HTTP 상태 코드

  • 2xx - 성공
  • 4xx - 에러
상태 코드이름설명
200OK요청이 성공했음을 나타냄. 클라이언트가 요청한 작업을 성공적으로 처리함을 의미함.
201Created새로운 리소스가 성공적으로 생성됨. 서버가 요청을 성공적으로 처리하고 새로운 리소스를 생성함을 의미함.
204No Content리소스 삭제 성공. 요청된 작업이 성공적으로 수행되었지만 응답 본문에는 컨텐츠가 없음을 의미함.
400Bad Request클라이언트의 요청이 잘못된 형식이거나 서버가 처리할 수 없는 경우 발생함.
401Unauthorized비인증 상태에서의 접근 시도. 요청된 리소스에 접근하기 위해서는 인증이 필요함을 의미함.
403Forbidden인증은 되었지만, 해당 리소스에 대한 권한이 없는 경우 발생함.
404Not Found요청한 리소스를 찾을 수 없음. 클라이언트가 요청한 리소스나 경로가 서버에 존재하지 않음을 의미함.
405Method Not Allowed요청된 메서드를 사용할 수 없음. 요청된 URL에서 허용되지 않는 HTTP 메서드를 사용했을 때 발생함.
409Conflict리소스 충돌이 발생한 경우. 클라이언트 요청이 서버 상태와 충돌하는 경우에 발생함.
500Internal Server Error서버 내부 오류. 서버에서 요청을 처리하는 동안 예기치 않은 오류가 발생한 경우에 발생함.
profile
미래의 나를 위한 기록

0개의 댓글