2017-11-21 18 views
1

저는 Sinon을 처음 사용하는 사람에게 매우 익숙합니다. 내가 작성한 다음 테스트가 있는데, res.status이 항상 호출되지 않아 다시 돌아 오기 때문에 실패합니다.Mocha, Chai 및 Sinon을 사용하여 Express 컨트롤러 메서드를 올바르게 테스트하는 방법

import chai from 'chai'; 
import 'chai/register-should'; 
import sinon from 'sinon'; 
import sinonChai from 'sinon-chai'; 
import { db } from '../../models'; 
import * as loginController from '../../controllers/login'; 

chai.use(sinonChai); 

describe('Login controller',() => { 

    describe('post function',() => { 
    let findOne, req, status, send, res; 

    beforeEach(() => { 
     findOne = sinon.stub(db.User, 'findOne'); 
     findOne.resolves(null); 
     req = { body: { email: '[email protected]', password: 'testpassword' }}; 
     status = sinon.stub(); 
     send = sinon.spy(); 
     res = { send: send, status: status }; 
     status.returns(res); 
     loginController.post(req, res); 
    }); 
    afterEach(() => { 
     findOne.restore(); 
    }); 
    it('should return a 401 status for an invalid email', (done) => { 
     res.status.should.be.calledWith(401); 
     findOne.restore(); 
     done(); 
    }); 

    }); 
}); 

컨트롤러의 메소드는 매우 간단합니다. 그것은 먼저 findOne 방법을 sequelize를 사용합니다. 그것을 찾지 못하면 일치하는 그것이 401 여기처럼 그 모습을 던져해야합니다 이메일 : 내가 테스트를 실행하면 그것이 상태를 반환해야 else 문에 도착 않습니다

export function post(req,res) { 
    const email = req.body.email; 
    const password = req.body.password; 

    db.User.findOne({ 
    where: {email: email} 
    }).then(user => { 
    if (user) { 
     // Other stuff happens here 
    } else { 
     res.status(401).send('That email address does not exist in our system.'); 
    } 
    }).catch((error) => { 
    res.status(500).send(error.message); 
    }); 
} 

하지만, 테스트가 실패하고 로그를 확인할 때 res.status이 호출되지 않는다고 표시됩니다.

답변

2

여기서 문제는 사양이 동기적이고 약속을 고려하지 않는다는 것입니다.

그것은 테스트 용이성을 이유로 약속을 반환하는 의미가 있습니다 : 경로 핸들러가 async 기능의 경우

export function post(req,res) { 
    ... 
    return db.User.findOne(...) 
    ... 
} 

이 자연스럽게 수행 할 수 있습니다. 모카는 약속을 지원하기 때문에

, 사양은 async 기능을 대신뿐만 아니라 done 콜백 사용할 수 있습니다

it('should return a 401 status for an invalid email', async() => { 
    const handlerResult = loginController.post(req, res); 
    expect(handlerResult).to.be.a('promise'); 

    await handlerResult; 
    res.status.should.be.calledWith(401); 
}); 
+0

나는이 노력하고있어,하지만 그것은 익명 함수 선언으로'async'을 가진 좋아하지 않는다. 문법이 맞습니까? 오류 : 'ReferenceError : regeneratorRuntime is defined' – LoneWolfPR

+0

맞습니다. 설정에서 Babel 구성에 문제가 있습니다. 귀하의 오류로 Google. – estus

+0

예. babel-polyfill이 필요합니다. – LoneWolfPR