Jest + Supertest 로 Koa API 테스트하기

Seokwon Han·2021년 3월 17일
1

개발일지

목록 보기
5/7

Jest vs Mocha

Jest로 Koa의 API를 테스트하기 위해서 겪었던 일들을 적기 위해 글을 썼다. 테스트 자동화에 가장 많이 쓰이는 도구 중 하나인 Mocha도 있지만 Jest가 설정이 간편하고 하나의 패키지에 모든게 들어있다고 하여 Jest를 사용하기로 했다.
(Jest는 mocha + should 의 조합이라고도 한다.)

사용법

Jest 와 Supertest 설치

yarn add --dev jest supertest

테스트는 개발할때만 사용할것이므로 개발 의존성으로 설치를 했다.
Jest는 테스트를 위한 라이브러리이고 Supertest는 API 테스트를 할 때 http 요청과 응답을 간편하게 만들어주는 라이브러리이다.

설정

// jest.config.js

module.exports = {
    // Mongoose는 jest의 default environment 을 제공하지 않으므로
    // Node.js로 변경
    testEnvironment: 'node',

    // 모듈 require 경로
    moduleDirectories: [
        "node_modules",
        "src"
    ]
};

맨처음엔 package.json 파일에 "jest" 필드를 넣어서 설정할 수 있다고 하길래 설정을 했다. 하지만 Mongoose를 사용하는 환경은 testEnvironment를 다르게 설정해줘야 한다고 알려주는 친절한 warning이 떠서 jest.config.js 파일에 작성하라길래 그냥 따라서 했다.(root 경로에 생성)
http://mongoosejs.com/docs/jest.html

moduleDirectories는 Jest 실행 시 외부와 내부모듈의 경로를 알려주는 설정이다. 프로젝트 내에서 모듈을 불러올 때 절대경로를 사용했기 때문에 이렇게 설정해주었다.

그다음엔 package.json 파일에 test 스크립트를 추가해주면 된다.

...
"scripts": {
	"test": "jest"
},
...

이로써 터미널에 yarn test를 치면 테스트 코드가 돌아간다.

테스트코드 작성

먼저 테스트를 하기 위해선 서버를 실행한 server 객체가 필요하다. 따라서 index.js 의 server 를 export 해주어야한다.

// src/index.js

const Koa = require('koa');
const app = new Koa();

...
// 중간 코드
...

// PORT 값이 설정되어있지 않다면 4000 을 사용합니다.
const port = process.env.PORT || 4000;

const server = app.listen(port, () => {
    console.log('bgs server is listening to port ' + port);
});

module.exports = server;

auth.controller.js 중 회원가입 API는 다음과 같이 작성되어있다.
Method: POST
Endpoint: /api/auth/register/local

// src/api/auth/auth.controller.js

// 로컬 회원가입
exports.localRegister = async (ctx) => {
    // 아이디 / 이메일 중복 체크
    const existing = await Accounts.findByEmailOrUsername(ctx.request.body);

    if (existing) {
        // 중복되는 아이디/이메일이 있을 경우
        ctx.status = 400;
        // 어떤 값이 중복되었는지 알려줍니다
        ctx.body = {
            key: existing.email.address 
          	=== ctx.request.body.email ? 'email' : 'username'
        };
        return;
    }

    // 생략
};

Jest는 .test.js로 작성된 파일이나 __test__폴더에 들어있는 test 파일들을 일괄적으로 테스트한다. 폴더와 파일을 생성하고 해당 API를 테스트하기 위해 중복되는 유저이름으로 회원가입을 했을 때 테스트코드를 작성해 보았다.

// test/auth.test.js

const request = require('supertest');
const server = require('index');

describe('Auth API local register 테스트', () => {
    test('중복되는 아이디로 가입 시 409응답코드와 {key:username}객체 응답', async () => {
        const response = await request(server)
        .post('/api/auth/register/local')
        .send({
            username: 'googleUser',
            email: 'hhsw1606@asdf.com',
            password: '123123'
        });
        expect(response.status).toEqual(409);
        expect(response.body).toEqual({
            key: 'username'
        });
    });
});

test로 테스트 하나를 작성할 수 있다. 테스트케이스에 해당한다
describe로 여러 테스트케이스를 묶을 수 있다. 해당 블록 안에서는 스코프가 공유되므로 변수를 같이 사용할 수 있다. 또한 테스트 실행 시 테스트 메시지가 nesting되어 나타난다.

supertest의 request 함수를 사용해서 http요청을 보냈다. server가 구동된 뒤에 요청을 보내야 하므로 비동기식으로 코드를 작성해야한다.

자주 사용되는 Matcher 의 종류는 다음과 같다.

  • toEqual() : 두 객체의 일치 여부 확인
  • toBe() : 두 값의 일치 여부 확인
  • toBeTruthy(), toBeFalsy() : true, false인지 확인
  • toHaveLength() : 객체의 길이 확인
  • toContain() : Array에 특정 요소 포함 여부 확인
  • toThrow() : 함수 호출 시 에러 발생 여부 확인

결과


테스트 결과 정상적으로 수행된 것을 확인했다. 하지만 테스트 실행이 완료되었음에도 종료가 되지 않는다. 노란 글씨로 문제점을 대충 짚어주는데 방법을 찾아서 적용해봐야겠다.

profile
개발하면서 새로 배우거나 경험한 내용을 정리하고 그 외의 공부한 내용을 기록하는 곳입니다.

0개의 댓글