사용자 목록 조회 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
'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 |
댓글