반응형

저번 유닛 테스트에 이어서 e2e 테스트를 해보도록 하겠습니다.

[NestJS] 유닛 테스트(Unit Testing)

 

e2e Test

e2e Test는 end-to-end test로 사용자 입장에서 테스트를 하는 것입니다.

 

 

app.e2e-spec.ts

it('/ (GET)', () => {
    return request(app.getHttpServer())
      .get('/')
      .expect(200)
      .expect('Welecome to my API');
  });
  • request와 url을 받고, get으로 요청해서 200과 Welecome to my API라는 메시지를 받아야 합니다.

 

getAll()

it('/movies (GET)', () => {
    return request(app.getHttpServer())
      .get('/movies')
      .expect(200)
      .expect([]);
  })

 

post

  • 서버에 request 해서 movies에 post 할 때, 이 정보를 보내면 201을 받는지 테스트합니다.
describe('/movies', () => {
    it('GET', () => {
      return request(app.getHttpServer())
        .get('/movies')
        .expect(200)
        .expect([]);
    });
    it('POST', () => {
      return request(app.getHttpServer())
        .post('/movies')
        .send({
          title: "Test",
          year: 2000,
          genres: ['test']
        })
        .expect(201); // 생성
    })
  });

 

delete()

  • 404 notfountexception 이 나오는지 확인합니다.
it('DELETE', () => {
      return request(app.getHttpServer())
        .delete('movies').expect(404);
    })

 

todo

describe('/movies/:id', () => {
    it.todo('GET');
    it.todo('DELETE');
    it.todo('PATCH');
  });

 

beforeEach

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

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

    app = moduleFixture.createNestApplication();
    await app.init();
  });
  • 테스트가 새로 생길 때마다 새로운 애플리케이션을 만듭니다.
  • 새로 앱을 만들 때마다 데이터베이스가 텅텅 비어있으니까 새로 데이터를 넣어줘야 하는 귀찮음이 있습니다.

→ 그래서 beforeEach를 beforeAll로 바꿔보도록 하겠습니다.

beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();
  • beforeAll()로 바꾸고 it.todo() 부분도 변경해줍니다.
describe('/movies/:id', () => {
    it('GET 200', () => {
      return request(app.getHttpServer()).get('/movies/1').expect(200);
    });
    it.todo('DELETE');
    it.todo('PATCH');
  });

→ 위에서 post로 데이터를 만들었으니깐 200이 뜰 줄 알았는데 에러 발생!!

→ 왜? 200이 아니라 404이기 때문에

 

  1. movies.service.ts로 들어가서 getOne()에 넘긴 id 출력
getOne(id: number): Movie {
        console.log(id);
        ...
    }

id 값 잘 넘어옴

 

Insomnia에서 확인

빈 배열이 들어간 것을 확인

 

POST로 데이터를 담고 getOne()으로 테스트합니다.

insomnia 에서는 잘 나옴

 

💡 근데 테스트할 때는 왜 안 나올까요?

 

  • id의 type을 확인해봅니다.
getOne(id: number): Movie {
        console.log(typeof id);
				... }

number가 나옵니다.

반응형
  • npm run test:e2e로 확인해봅니다.

→ 테스트에서는 string으로 나옵니다.

→ movie.id 는 number이고, id는 string이기 때문에 찾을 수 없다고 뜨는 것

 

💡 왜 실서버에서의 id는 number이고, 테스트 서버에서는 string으로 나올까요?

 

 

main.ts

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe({
    whitelist:true, // 아무 decorator 도 없는 어떤 property의 object를 거름
    forbidNonWhitelisted: true, // 잘못된 property의 리퀘스트 자체를 막아버림
    transform: true, // 실제 원하는 타입으로 변경해줌
  }));
  await app.listen(3000);
}
  • transform이라는 것을 넣었습니다.
  • 그래서 getOne()을 호출할 때 id 가 내가 원하는 number 타입으로 변경됩니다.
getOne(id: number): Movie
  • 하지만 문제는 url 은 string입니다.
    • 어떤 이유인지 e2e 테스트에서 transform 이 작동하지 않습니다.
      → 왜냐하면 e2e 테스트할 때 새로운 앱을 생성을 하는데 어떤 pipe 에도 올리지 않음..

 

💡 테스트에도 실제 애플리케이션 환경을 그대로 적용시켜줘야 합니다!!

 

 

app.e2e-spec.ts

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

    app = moduleFixture.createNestApplication();
    app.useGlobalPipes(new ValidationPipe({
      whitelist:true, // 아무 decorator 도 없는 어떤 property의 object를 거름
      forbidNonWhitelisted: true, // 잘못된 property의 리퀘스트 자체를 막아버림
      transform: true, // 실제 원하는 타입으로 변경해줌
    }));
    await app.init();
  });
...
  • 다시 테스트해보면 잘 나오는 것을 확인할 수 있습니다.

 

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);
    });
  });

 

  • 잘못된 데이터를 가진 movie를 create 하는지 테스트
it('POST 201', () => {
      return request(app.getHttpServer())
        .post('/movies')
        .send({
          title: "Test",
          year: 2000,
          genres: ['test']
        })
        .expect(201); // 생성
    });

    it('POST 400', () => {
      return request(app.getHttpServer())
        .post('/movies')
        .send({
          title: "Test",
          year: 2000,
          genres: ['test'],
          other: 'thing'
        })
        .expect(400); // 생성
    });

 

 

마치면서

오늘은 저번 유닛 테스트에 이어서 E2E 테스트를 해보았습니다.

매번 프로젝트를 할 때마다 테스트 코드 작성을 습관화하려고 합니다.

모든 유닛 테스트를 할 수 없다면 E2E 테스트만이라도 해서 기능이 잘 작동하는지 테스트해보도록 합시다.

 

반응형

'Backend > Nestjs' 카테고리의 다른 글

[NestJS] JWT AuthGuard/Strategy  (0) 2024.01.04
[NestJS] NestJS 란?  (0) 2022.06.10
[NestJS] Swagger 생성하기  (0) 2022.02.21
[NestJS] 유닛 테스트(Unit Testing)  (0) 2022.02.16
[NestJS] Docker 304 undefined 에러  (0) 2022.02.14

+ Recent posts