2015년 7월 29일 수요일

Error: timeout of 5000ms exceeded. Ensure the done() callback is being called in this test.

발생현상]

Error: timeout of 5000ms exceeded. Ensure the done() callback is being called in this test.

node.js에서 Mocha를 이용해서 테스트 실행중 특정 시점이후 발생하는 오류

node.js에서 MySql에서 사용자 정보 조회, 등록을 5번의 테스트 case로 수행함.
이때 DB Connection Pool의 connectionLimit은 "3"으로 설정되어 있음. 

test case : 회원가입
    describe("회원가입 ->", function() {
        it ("회원가입 실패(필수값 누락)", function(done) {
            var data = {
                user_id: user_id,
                password : password,
                user_name : '김치손',
                email : '',
                phone : '',
                cellphone : '',
                sex : '',
                logintype : mem_type
            };
            request(svr)
                .post("/member/register")
                .send(data)
                .expect(200)
                .end(function(err, res) {
                    if (err) return done(err);
                    expect('ER_BAD_NULL_ERROR').to.equal(res.body.code);
                    done();
                });
        });


routes.js : 
// 회원 정보를 저장
router.post('/register', function(req, res, next) {
    console.log(req.body);

    var loginType = req.body.logintype;
    var vUserId = req.body.user_id;

    var datas = [
        req.body.user_id,
        req.body.user_name,
        req.body.password,
        req.body.nickname,
        req.body.email,
        req.body.sex,
        req.body.phone,
        req.body.address,
        req.body.logintype
    ];
    // TODO 이메일 중복, 체크 로직 추가

        memberProvider.insertMember(datas, function(err, sInsertId) {
            if (err) {
                res.send(CONSTS.getErrData(err.code));
                return;
            }
            res.send(CONSTS.getErrData('0000'));
        });
});

db.js
var mysql = require('mysql');
var pool = mysql.createPool({
    connectionLimit: 3,
    user: 'xxxx',
    password: 'xxxx',
    database: 'xxxx'
});

var sqlMember = {
     //신규 회원 가입
    "insertNew": "insert into tb_member(user_id, user_name, " +
        "user_password, user_nickname, email, sex, phone, address, mem_type, reg_date) " +
        "values(?, ?, ?, ?, ?, ?, ?, ?, ?, now())",
    // 회원 정보 갱신
    "upateInfo": "update tb_member set user_password = ?, edit_date = now() " +
        "where id = ? ",
    // 회원 정보 조회
    "selectInfo": "select * from tb_member where user_id = ? and mem_type = ?",
    // 회원 정보 삭제
    "deleteMember": "delete from tb_member where user_id = ? and mem_type = ?",
};

MemberProvider = function() {

}

MemberProvider.prototype.insertMember = function (datas, callback) {
    // console.log('insertMember : ' + datas);
    // TODO Password 저장시 암호화 필요함.
    //      암호화 후 로그인에서 비밀번호 체크 로직 보완 필요함.
    pool.getConnection(function (err, conn) {
        conn.query(sqlMember.insertNew, datas, function(err, rows) {
            if (err) {
                conn.release;
                console.error("err : " + err);
                callback(err);
            } else {
                console.log("rows : " + JSON.stringify(rows));
                conn.release;
                callback(null, rows.insertId);
            }
        });
    });
};

수행결과
...
data : mocha02,C
  1) 치과병원 회원 가입,로그인 테스트 -> 치과병원 -> 로그인 성공
    치과병원 회원 가입,로그인 테스트 -> 치과병원 -> 로그인 실패: { user_id: 'mocha02', password: 'a', mem_type: 'C' }
queryID : selectInfo
data : mocha02,C
  2) 치과병원 회원 가입,로그인 테스트 -> 치과병원 -> 로그인 실패
  3) 치과병원 회원 가입,로그인 테스트 -> 치과병원 -> 치과병원정보 삭제
  3 passing (15s)
  3 failing

  1) 치과병원 회원 가입,로그인 테스트 -> 치과병원 -> 로그인 성공:
     Error: timeout of 5000ms exceeded. Ensure the done() callback is being called in this test.
 

  2) 치과병원 회원 가입,로그인 테스트 -> 치과병원 -> 로그인 실패:
     Error: timeout of 5000ms exceeded. Ensure the done() callback is being called in this test.
 

  3) 치과병원 회원 가입,로그인 테스트 -> 치과병원 -> 치과병원정보 삭제:
     Error: timeout of 5000ms exceeded. Ensure the done() callback is being called in this test.

발생원인]

Mocha test case 5번 모두가 비동기로 수행된다.
비동기로 수행된다는 것은 모두 동시에 DB에 접속해서 작업을 수행하게 된다.
이때, 문제는 동시에 5개의 test case 모두 db에 접속하려고 하므로 connectionLimit : 3의 제약에 따라서 대기하게 되므로 Timeout 오류가 발생하는 것이다.
수행결과 화면에 뿌려지는 결과는 수행결과를 그냥 순차적으로 표시하는 것으로 보인다.

이제까지 내가 착각한 부분 Mocha가 순차적으로 하나씩 수행하므로 DB connection Pool 의 connectionLimit에는 영향이 없다고 판단한 착오가 있었다.

해결방법]

동시 수행하는 test case 만큼 db connection pool의 설정에서 limit 개수를 올려준다.
var mysql = require('mysql');
var pool = mysql.createPool({
    connectionLimit: 10,
    user: 'xxxx',
    password: 'xxxx',
    database: 'xxxx'
});


이 글은 Evernote에서 작성되었습니다. Evernote는 하나의 업무 공간입니다. Evernote를 다운로드하세요.

댓글 없음:

댓글 쓰기