devlog_zz

[NestJS] #4 E2E Testing 본문

Back End/NestJS

[NestJS] #4 E2E Testing

YJ_SW 2022. 9. 15. 17:15
728x90

4.0 Testing movies

E2E 테스트는 moive와 관련된 애플리케이션의 모든 부분을 테스트할 때 필요하다.

supertest라는 라이브러리 패키지가 존재한다.

it('/ (GET)', () => {
    return request(app.getHttpServer())
      .get('/')
      .expect(200)
      .expect('Hello World!');
  });

Get 으로 API Request 보내며 테스트

url에 대한 요청을 테스팅

⇒ Controller, Service, Pipe의 결과에 대해 모든 테스트를 하고 있다는 뜻이기도 하다.

test > app.e2e-spec.ts

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';

describe('AppController (e2e)', () => {
  let app: INestApplication;

  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

  it('/ (GET)', () => {
    return request(app.getHttpServer())
      .get('/')
      .expect(200)
      .expect('Welcome to my Movie API');
  });
  describe("/moives",() => {
    it("GET",() => {
      return request(app.getHttpServer())
      .get("/movies")
      .expect(200)
      .expect([]);
    })
    it("CREATE",() => {
      return request(app.getHttpServer())
      .post("/movies")
      .send({title:'test',year:2022,genres:['test']})
      .expect(201)
    })
    it("DELETE",() => {
      return request(app.getHttpServer())
      .delete("/movies")
      .expect(404)
    })
  })

 
});

보통 개발자는 테스팅을 할 때 2개의 데이터베이스를 가지고 있다. 하나는 테스팅을 위한 것이고 다른 하나는 평소에 사용하는 것이다.

테스팅 데이터베이스에서는 데이터를 삭제, 생성하는 일이 빈번한데 우리의 경우 처음부터 빈 데이터베이스이기 때문에 이렇게 테스팅을 해야 한다.

4.1 Testing GET movies id

NestJS는 테스트마다 어플리케이션을 생성하고 있다.

beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

각 테스트를 위한 어플리케이션이다.

npm run start:dev 한 어플리케이션과는 다른 것이다.

테스트가 새로 생길 떄마다 새로운 어플리케이션을 만들기 원하지 않는다. create 한 결과물을 테스트를 진행하는 동안 계속 기억하고 있었으면 좋겠다면 beforeEach 를 beforeAll 로 바꾸면 된다.

describe("/movies/:id",() => {
    it.todo("GET 200", () => {
      return request(app.getHttpServer()).get("/movies/1").expect(200)
    })
    it.todo("DELETE")
    it.todo("PATCH")
  })

beforeAll 로 바꾸고 실행을 하면 에러가 발생한다.

insomnia에서 실행되는 서버는 실제로 어플리케이션 위에서 돌아가는 서버이다.

테스팅 서버와는 다른 애플리케이션이다.

movies.service.ts

getOne(id:number):Movie {
				**console.log(typeof id)**
        const movie = this.movies.find(movie => movie.id === id);
        if(!movie){
            throw new NotFoundException(`Movie with id ${id} Not Found`)
        }
        return movie
    }

함수가 호출될 때 id의 타입을 찍어보면

실제로 사용하는 서버에서는 (insomnia 호출 )id 타입이 number 이지만, 테스팅 서버에서 id타입은 string이다.

main.ts 에서 useGlobalPipes를 활용해 transform : true 옵션을 주었었다. transform은 controller에서 타입을 지정한 타입으로 바꾸어주었다.

url은 string이다. transform 덕분에 number로 변환이 된다. e2e 테스트에서는 transform이 동작하지 않는다.

app.e2e-spec.ts > beforeAll 함수 내에서 어플리케이션을 생성한다.

app = moduleFixture.createNestApplication(); 

이 때 어떤 pipe에도 올리지 않았다.

e2e 테스트를 할 때 테스트에서도 실제 어플리케이션의 환경을 그대로 적용시켜줘야 된다.

app.e2e-spec.ts

beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    app.useGlobalPipes(new ValidationPipe(
      { 
        whitelist: true,
        forbidNonWhitelisted: true,
        transform: true,
      }
    ))
    await app.init();
  });

이 전에 동작하지 않았던 이유는 transform은 main.ts에만 있었고 spec.ts 에는 없어서 동작하지 않았던 것이다.

4.2 Tesing PATCH and DELETE movies id

describe("/movies/:id",() => {
    it("GET 200", () => {
      return request(app.getHttpServer()).get("/movies/1").expect(200)
    })
    it("GET 404", () => {
      return request(app.getHttpServer()).get("/movies/999").expect(404)
    })
    it("PATCH",() => {
      return request(app.getHttpServer()).patch("/movies/1").send({title:'update test'}).expect(200)
    })
    it("DELETE",() => {
      return request(app.getHttpServer()).delete("/movies/1").expect(200)
    })
  })

 

 

출처

https://nomadcoders.co/nestjs-fundamentals

https://docs.nestjs.com/

728x90

'Back End > NestJS' 카테고리의 다른 글

[NestJS] #3 Unit Testing  (0) 2022.09.15
[NestJS] #2 Rest API  (0) 2022.09.15
[NestJS] #1 Architecture of NestJS  (0) 2022.09.15
[NestJS] #0 INTRODUCTION  (0) 2022.09.15
Comments