2017-11-21 14 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の続編を使用します。私がテストを実行すると

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); 
    }); 
} 

それは状態を返すが、しなければならないelse文に着くん:それは、一致が見つからない場合は、それがここで401は、それがどのように見えるのですスローする必要があります電子メールで送信しますテストが失敗し、ログを確認すると、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

関連する問題