본문 바로가기
Javascript/Node.js

SuperTest 연습

by 모스키토끼 2020. 6. 11.

사용자 목록 조회 API 테스트

Spec

  • 성공
    • 유저 객체를 담은 배열로 응답
    • 최대 limit 갯수만큼 응답
  • 실패
    • limit이 숫자형이 아니면 400을 응답
    • offset이 숫자형이 아니면 400을 응답(DB를 붙인 후 테스트 예정)

코드

//index.spec.js
const request = require('supertest');
const should = require('should');
const app = require('./index');

describe('GET /users는', ()=>{
    describe('성공시', ()=>{
        it('유저 객체를 담은 배열로 응답한다 ',(done)=>{
            request(app)
                .get('/users')
                .end((err,res)=>{
                    res.body.should.be.instanceOf(Array);
                    done();
                });
        });

        it('최대 limit 갯수만큼 응답한다 ', (done) =>{
            request(app)
                .get('/users?limit=2')
                .end((err,res)=>{
                    res.body.should.have.lengthOf(2);
                    done();
                });
        });
    });
    describe('실패시 ', ()=>{
        it('limit이 숫자형이 아니면 400을 응답한다', (done) =>{
            request(app)
                .get('/users?limit=two')
                .expect(400)
                .end(done);
        });
    });

});

//index.js
const express = require('express');
const morgan = require('morgan');
const app = express();

const users = [
    {id: 1, name:'alice'},
    {id: 2, name:'bek'},
    {id: 3, name:'chris'},
];

app.use(morgan('dev'));
app.get('/users', function (req, res){
    req.query.limit = req.query.limit || 10;
    const limit = parseInt(req.query.limit,10);
    if(Number.isNaN(limit)){
        return res.status(400).end();
    }
    res.json(users.slice(0, limit));
});

app.listen(3000, function(){
	console.log('Server is running');
});

module.exports = app;

사용자 조회 API 테스트

spec

  • 성공
    • id가 1인 유저 객체를 반환
  • 실패
    • id가 숫자가 아닐경우 400으로 응답
    • id로 유저를 찾을 수 없는 경우 404로 응답

코드

//index.spec.js
//...
describe('GET /users/1는', ()=>{
    describe('성공시 ', ()=>{
        it('id가 1인 유저 객체를 반환한다', (done) =>{
            request(app)
                .get('/users/1')
                .end((err, res) =>{
                    res.body.should.have.property('id', 1);
                    done();
                });
        });
    });
    describe('실패시 ', ()=>{
        it('id가 숫자가 아닐 경우 400으로 응답한다.', (done)=>{
            request(app)
                .get('/users/one')
                .expect(400)
                .end(done)
        });
        it('id로 유저를 찾을 수 없는 경우 404로 응답한다.', (done)=>{
            request(app)
                .get('/users/999')
                .expect(404)
                .end(done)
        });
    });
});

//index.js
//...
app.get('/users/:id', function(req, res){
    const id = parseInt(req.params.id,10);
    if(Number.isNaN(id)) return res.status(400).end();

    const user = users.filter(user=>user.id === id)[0];
    if(!user) return res.status(404).end();
    res.json(user);
});

사용자 삭제 API 테스트

spec

  • 성공
    • 204를 응답
  • 실패
    • id가 숫자가 아닐 경우 400으로 응답

코드

//index.spec.js
//...
describe('GET /users/1', () =>{
    describe('성공시', ()=>{
        it('204를 응답한다', (done) =>{
            request(app)
                .delete('/users/1')
                .expect(204)
                .end(done)
        });
    });
    describe('실패시', ()=>{
        it('id가 숫자가 아닌 경우 400으로 응답한다', (done) =>{
            request(app)
                .delete('/users/one')
                .expect(400)
                .end(done)
        });
    });  
});

//index.js
//...
app.delete('/users/:id', (req,res)=>{
    const id = parseInt(req.params.id,10);
    if(Number.isNaN(id))return res.status(400).end(); 
    console.log(id)
    users = users.filter(user=>user.id !== id);
    res.status(204).end();
})

사용자 추가 API 테스트

spec

  • 성공
    • 201상태코드 반환
    • 생성된 유저 객체 반환
    • 입력한 name 반환
  • 실패
    • name 파라미터 누락 시 400 반환
    • name이 중복일 경우 409 반환

코드

- before(Mocker):
테스트케이스가 실행되기 전에 실행되는 함수
- bodyParser:
json형태로 파싱할 때 사용 -> 미들웨어 형태로 코드에 적용
(express 4.x에서는 body parser를 기본으로 제공하고 있음 때문에 따로 추가 필요 X)
- multer:
이미지같은 큰 데이터를 사용할 때 사용

//index.spec.js
//...
describe('POST /users', ()=>{
    describe('성공시', ()=>{
        let name = 'bigring';
        let body;
        before(done=>{
            request(app)
                .post('/users')
                .send({name})
                .expect(201)
                .end((err, res) =>{
                    body = res.body;
                    done();
                })
        })
        it('생성된 유저 객체를 반환한다 ', ()=>{ //비동기 테스트가 아니므로 done 필요x
            body.should.have.property('id');
        });
        it('입력한 name을 반환한다 ', () =>{
            body.should.have.property('name', name)
        });
    });
    describe('실패시', ()=>{
        it('name 파라미터 누락시 400을 반환한다', (done)=>{
            request(app)
                .post('/users')
                .send({})
                .expect(400)
                .end(done)
        });
        it("name이 중복일 경우 409를 반환한다", done =>{
            request(app)
                .post('/users')
                .send({name: 'bigring'})
                .expect(409)
                .end(done)
        });
    });
});

//index.js
//...
app.use(express.json());
app.use(express.urlencoded({extended:true}))
//...
app.post('/users', (req, res) =>{
    const name = req.body.name;
    if(!name) return res.status(400).end();

    const isConflict = users.filter(user =>user.name === name).length
    console.log(isConflict,"===============")
    if(isConflict) return res.status(409).end();

    const id = Date.now();
    const user = {id, name};
    users.push(user);
    res.status(201).json(user);
})

사용자 수정 API 테스트

spec

  • 성공
    • 변경된 name을 응답
  • 실패
    • 정수가 아닌 id일 경우 400 응답
    • name이 없는 경우 400 응답
    • 없는 유저일 경우 404 응답
    • 이름이 중복일 경우 409 응답

코드

//index.spec.js
//...
describe('PUT /users/:id', ()=>{
    describe('성공시', ()=>{
        it('변경된 name을 응답한다', (done)=>{
            const name = 'den';
            request(app)
                .put('/users/3')
                .send({name})
                .end((err,res)=>{
                    res.body.should.have.property('name', name);
                    done();
                });
        });
    });

    describe('실패시', ()=>{
        it('정수가 아닌 id일 경우 400을 응답한다 ', (done)=>{
            request(app)
                .put('/users/one')
                .expect(400)
                .end(done);
        });
        it('name이 없는 경우 400을 응답한다 ', (done)=>{
            request(app)
                .put('/users/1')
                .expect(400)
                .end(done);
        });
        it('없는 유저일 경우 404을 응답한다 ', (done)=>{
            request(app)
                .put('/users/999')
                .send({name:'foo'})
                .expect(404)
                .end(done);
        });
        it('이름이 중복일 경우 409을 응답한다 ', (done)=>{
            request(app)
                .put('/users/3')
                .send({name:'bek'})
                .expect(409)
                .end(done);
        });
    });
});

//index.js
//...
app.put('/users/:id', (req,res)=>{
    const id = parseInt(req.params.id, 10);
    if(Number.isNaN(id)) return res.status(400).end();

    const name = req.body.name;
    if(!name) return res.status(400).end();
    
    const isConflict = users.filter(user=>user.name === name).length

    if(isConflict) return res.status(409).end();

    const user = users.filter(user=> user.id === id)[0];
    if(!user) return res.status(404).end();

    user.name = name;

    res.json(user);
});

결과

 

Reference

https://expressjs.com/ko/4x/api.html

 

Express 4.x - API 참조

Express 4.x API express() Creates an Express application. The express() function is a top-level function exported by the express module. var express = require('express') var app = express() Methods express.json([options]) This middleware is available in Ex

expressjs.com

https://www.inflearn.com/course/%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%A3%BC%EB%8F%84%EA%B0%9C%EB%B0%9C-tdd-nodejs-api/

 

테스트주도개발(TDD)로 만드는 NodeJS API 서버 - 인프런

javascript 언어로 백엔드 개발을 할 수 있는 NodeJS 를 학습해 봅니다. 테스트 주도 개발 (TDD) 방법으로 NodeJS를 이용해 API 서버 개발을 배워보고 학습할 수 있는 강좌입니다. NodeJS의 대표적인 웹프레�

www.inflearn.com

 

'Javascript > Node.js' 카테고리의 다른 글

passport 적용  (2) 2020.07.08
ORM(Sequelize) & 데이터베이스  (0) 2020.06.15
테스트 주도 개발(TDD)  (0) 2020.06.10
익스프레스JS  (0) 2020.06.10
NodeJS의 특징  (0) 2020.06.09

댓글