on
노드 서비스 테스트하기
노드 서비스 테스트하기
테스트 준비하기
테스트를 하는 이유
자신이 만든 서비스가 제대로 동작하는지 테스트해야 함
기능이 많다면 수작업으로 테스트하기 힘듦
프로그램이 프로그램을 테스트할 수 있도록 자동화함
테스트 환경을 최대한 실제 환경과 비슷하게 흉내냄
아무리 철저하게 테스트해도 에러를 완전히 막을 수는 없음
테스트를 하면 좋은 점
하지만 허무한 에러로 인해 프로그램이 고장나는 것은 막을 수 있음
한 번 발생한 에러는 테스트로 만들어두면 같은 에러가 발생하지 않게 막을 수 있음
코드를 수정할 때 프로그램이 자동으로 어떤 부분이 고장나는 지 알려줌
Jest 설치하기
npm i –D jest
Nodebird 프로젝트를 그대로 사용함
테스트 실행해보기
routes 폴더 안에 middlewares.test.js 작성
테스트용 파일은 파일명에 test나 spec이 있으면 됨
npm test로 test나 spec 파일들을 테스트함.
테스트를 아무것도 작성하지 않았으므로 에러 발생(테스트 실패)
첫 테스트 코드 작성하기
middlewares.test.js 작성하기
test 함수의 첫 번째 인수로 테스트에 대한 설명
두 번째 인수인 함수에는 테스트 내용을 적음
expect 함수의 인수로 실제 코드를, toEqual 함수의 인수로는 예상되는 결괏값을
expect와 toEqual의 인수가 일치하면 테스트 통과
실패하는 경우
두 인수를 다르게 작성하면 실패 ( 메시지를 살펴볼 것 )
유닛 테스트
middlewares 테스트하기
middlewares.test.js 작성하기 테스트 틀 잡기
describe로 테스트 그룹화 가능
req, res 모킹하기
미들웨어 테스트를 위해 req 와 res 를 가짜로 만들어주어야 함
jest.fn으로 함수 모킹 가능
// routes/middlewares.test.js const { isLoggedIn, isNotLoggedIn } = require('./middlewares') describe('isLoggedIn', ()=>{ const res = { status: jest.fn(()=>res), send: jest.fn(), }; const next = jest.fn(); test('로그인되어 있으면 isLoggedIn이 next를 호출해야 함',()=>{ const req = { isAuthenticated: jest.fn(() => true), }; isLoggedIn(req,res,next); expect(next).toBeCalledTimes(1); }); test('로그인되어 있지 않으면 isLoggedIn이 에러를 응답해야 함',()=>{ const req = { isAuthenticated: jest.fn(() => false), }; isLoggedIn(req,res,next); expect(res.status).toBeCalledWith(403); expect(res.send).toBeCalledWith("로그인 필요"); }); })
expect 메서드
expect 에는 toEqual 말고도 많은 메서드 지원
toBeCalledWith 로 인수 체크
toBeCalledTimes 로 호출 회수 체크
// routes/middlewares.test.js describe('isNotLoggedIn',() =>{ const res = { status: jest.fn(()=>res), send: jest.fn(), redirect: jest.fn(), }; const next = jest.fn(); test('로그인되어 있지 않으면 isNotLoggedIn이 next를 호출해야 함',()=>{ const req = { isAuthenticated: jest.fn(() => false), }; isNotLoggedIn(req,res,next); expect(next).toBeCalledTimes(1); }); test('로그인되어 있으면 isNotLoggedIn이 에러를 응답해야 함',()=>{ const req = { isAuthenticated: jest.fn(() => true), }; isNotLoggedIn(req,res,next); const message = encodeURIComponent('로그인한 상태입니다.'); expect(res.redirect).toBeCalledWith(`/?error=${message}`); }); })
라우터 테스트 위해 분리하기
라우터도 미들웨어이므로 분리해서 테스트 가능
// controllers/user.js const User = require('../models/user'); exports.addFollowing = async (req, res, next) => { try { const user = await User.findOne({ where: { id: req.user.id } }); if (user) { await user.addFollowing(parseInt(req.params.id, 10)); res.send('success'); } else { res.status(404).send('no user'); } } catch (error) { console.error(error); next(error); } }
// routes/user.js const express = require('express'); const { isLoggedIn } = require('./middlewares'); const {addFollowing} = require('../controllers/user') const router = express.Router(); router.post('/:id/follow', isLoggedIn, addFollowing); module.exports = router;
라우터 테스트
Controllers/user.test.js 작성하기
// controllers/user.test.js const { addFollowing } = require('../controllers/user'); describe('addFollowing', () => { const req = { user: { id: 1 }, params: { id: 2 }, }; const res = { status:jest.fn(()=>res), send: jest.fn(), }; const next = jest.fn(); test('사용자를 찾아 팔로잉을 추가하고 success를 응답해야 함', async () => { await addFollowing(req, res, next); expect(res.send).toBeCalledWith('success'); }); test('사용자를 못 찾으면 res.status(404), send(no user)를 호출함', async () => { await addFollowing(req, res, next); expect(res.status).toBeCalledWith(404); expect(res.send).toBeCalledWith('no user'); }); test('DB에서 에러가 발생하면 next(error) 호출함',async ()=>{ const error = '테스트용 에러'; await addFollowing(req,res,next); expect(next).toBeCalledWith(error); }); });
실행 에러
https://www.inflearn.com/course/%EB%85%B8%EB%93%9C-%EA%B5%90%EA%B3%BC%EC%84%9C/dashboard/
본글의 모든 내용은 위 강의를 토대로 작성됩니다.
from http://jhg3410.tistory.com/32 by ccl(A) rewrite - 2021-11-22 01:00:38