2016-11-24 180 views
1

我一直在嘗試使用摩卡測試下面的代碼,但我總是得到錯誤。摩卡測試承諾

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

我想測試的代碼如下。

'use strict' 
const Promise = require('bluebird'); 

const successResponse = {status: 'OK'}; 
const failResponse = {status: 'FAIL'}; 

function dbStatusSuccess() { 
    return new Promise(function(resolve, reject) { 
     setTimeout(() => { 
      resolve(successResponse); 
     }, 2010); 

    }); 
} 

function dbStatusFail() { 
    return new Promise(function(resolve, reject) { 
     setTimeout(() => { 
      reject(failResponse); 
     }, 2000); 

    }); 
} 

module.exports = { 
    dbStatusSuccess, 
    dbStatusFail 
} 

這裏是我的測試。

'use strict' 
const Promise = require('bluebird'); 
const chai = require('chai') 
chai.use(require('chai-string')) 
chai.use(require('chai-as-promised')); 
const expect = chai.expect; 
chai.should(); 


const healthyCheck = require('./healthyCheck'); 

const resp = {status:'OK'}; 
const resp2 ={status: 'FAIL'}; 

describe('healthy-check end point',() => { 

    it('should return successful response when connected to database',() => { 

     return healthyCheck.dbStatusSuccess() 
          .then((res) => { 
           console.log(JSON.stringify(res, undefined, 2)); 
           return expect(res).to.equal(resp); 
          }).catch((err) => { 
           console.log(err); 
           return expect(err).to.deep.equal(resp2); 
          }); 


    }); 
}); 

我也得到一個錯誤{Asse田:在控制檯 'OK'} {預期狀態: 'OK'}等於{地位。我相信它是從.catch函數中的錯誤記錄中提取出來的。

編輯1. 從dbStatusSuccess函數中刪除了拒絕函數。

問題在於承諾花費2秒完成/失敗。如果setTimeout中設置的時間少於2秒,測試將通過。

+0

我發現一個問題,如果你的代碼,你爲什麼在函數dbStatusSuccess()中調用resolve()和reject()? – iKoala

+0

這是一個錯誤。我已經刪除了。但我不明白這會如何影響承諾的運作方式?問題是超時錯誤,即使我使用從它傳遞的done()函數,或者如果我返回承諾,我也會得到這個錯誤 – AshanPerera

+0

它會給出預期的結果,因爲承諾不能同時解析和拒絕。 – iKoala

回答

3

測試中的默認超時時間似乎是2000ms。你的代碼顯然需要更長的時間來完成因此,你必須提高超時限制。如註釋here你不應該使用箭頭功能,所以你可以安全地訪問this

然後你就可以增加你的超時時間,像這樣:

'use strict' 
const Promise = require('bluebird'); 
const chai = require('chai') 
chai.use(require('chai-string')) 
chai.use(require('chai-as-promised')); 
const expect = chai.expect; 
chai.should(); 


const healthyCheck = require('./healthyCheck'); 

const resp = {status:'OK'}; 
const resp2 ={status: 'FAIL'}; 

describe('healthy-check end point',() => { 

    it('should return successful response when connected to database', function() { 
     this.timeout(3000); 
     return healthyCheck.dbStatusSuccess() 
          .then((res) => { 
           console.log(JSON.stringify(res, undefined, 2)); 
           return expect(res).to.equal(resp); 
          }).catch((err) => { 
           console.log(err); 
           return expect(err).to.deep.equal(resp2); 
          }); 


    }); 
}); 

然後測試應該按預期運行。

+0

如果你想使用箭頭函數,this.timeout()將不起作用,因爲箭頭函數沒有這個綁定。 http://stackoverflow.com/a/35398816/3484580 – iKoala

+0

@iKoala是的我知道,這就是爲什麼我建議切換到一個普通的舊功能。如果你不想堅持箭頭功能(這不是問題中的要求),你可以使用你編輯的解決方案到你的答案。 – fahrradflucht

+0

那麼這個工作,但那麼返回承諾或調用完成()的點是什麼?我認爲通過做那些我們可以讓摩卡等待履行或拒絕的承諾? – AshanPerera

-1

嗯,我剛剛發現問題,你的測試很棘手。 您將超時定時器設置爲2010ms,但摩卡默認執行時間爲2000毫秒,因此您將始終從摩卡獲取錯誤。

我仍然認爲你不應該在返回的承諾鏈中創建.catch塊,它會阻止promise鏈傳播。

describe('healthy-check end point',() => { 

    it('should return successful response when connected to database',() => { 

     return healthyCheck.dbStatusSuccess() 
          .then((res) => { 
           console.log(JSON.stringify(res, undefined, 2)); 
           return expect(res).to.equal(resp); 
          }); 


    }).timeout(2500); //tell Mocha to wait for 2500ms 
}); 
+0

我仍然收到超時錯誤。 – AshanPerera

+0

爲你更新答案。 – iKoala

-1

您應該使用回調,例如:

it('reads some file', function(done) { 
    fs.readFile('someFile.json', function(err, data) { 
    if (err) return done(err); 
    assert(data != null, "File should exist."); 
    done(); 
    }); 
}); 

發生了什麼事是測試(「它」功能)返回自己的諾言結算前;使用完成表示在承諾解決時您將完成()完成()後才能完成測試。

http://tobyho.com/2015/12/16/mocha-with-promises/

https://mochajs.org/#working-with-promises

+1

這是不對的,摩卡支持Promise,所以在使用Promise時不需要回調。 – iKoala

+0

好吧,是的,我認爲它支持承諾,但根據摩卡文檔(在我發佈的鏈接上),您必須返回承諾,而帖子中的代碼在承諾的解決方案中主張(期望)。 –

+0

是的,這是正確的,你必須將你的斷言代碼放在分辨率塊內。我只是說過,在向摩卡咖啡回覆承諾時,你不應該使用它。如果你想在向摩卡咖啡館回覆承諾時使用它,它會給你帶來錯誤。 – iKoala

0
'use strict' 
    const Promise = require('bluebird'); 
    const chai = require('chai'); 
    chai.use(require('chai-string')); 
    chai.use(require('chai-as-promised')); 
    const expect = chai.expect; 
    chai.should(); 

    const healthyCheck = require('./healthyCheck'); 

    describe('healthy-check end point', function() { 

    it('should return successful response when connected to database', function(done) { 
     const resp = {status: 'OK'}; 

    healthyCheck.dbStatusSuccess() 
     .then((res) => { 
      console.log(JSON.stringify(res, undefined, 2)); 
      expect(res).to.equal(resp); 
      done(); 
     }).catch(done); 
    }); 
    }); 
  1. 在代碼示例我不回的承諾,所以我需要使用回調。異步測試中的使用回調有助於避免使用Error: timeout of 2000ms exceeded
  2. 請勿使用descibeit中的箭頭功能。 More info
+0

仍然是相同的錯誤 '錯誤:超過2000ms的超時。確保在此測試中調用了done()回調。' – AshanPerera

+1

我認爲不應該在傳遞給describe()的函數中完成回調。 – teroi