2017-07-03 49 views
1

I'm單元未處理的承諾拒絕測試一個Express功能是這樣的:測試ASYN調用拋出節點JS

function(request,response,someDependency){ 
    ... 
    someDependency.doStuff(arg1,arg2) 
    .then(function(someResponse){ 
     response.status(200).send({body: someResponse}); 
    }) 
    .catch(function(error){ 
     response.status(500).send({someResponse: 'error'); 
    }); 
} 

在我的單元測試(採用摩卡),我決定模仿我的反應,使用斷言裏面,還嘲笑我的依賴性:

我mockedResponse的抽象:

... 
exports.expectedStatus = function(status){ 
    this.expectedCode = status; 
} 
exports.status = function(realStatus){ 
    this.expectdCode = realStatus; 
    return this; 
} 
exports.send = function(body){ 
    assert.strictEqual(this.realStatus,this.expectedCode); 
} 

和我的依賴性的抽象是:

exports.setPromiseError(error){ 
    this.error = error; 
}; 
exports.doStuff(arg1,arg2){ 
    return new Promise(function (resolve, reject){ 
     if (!error) 
     resolve({this: 'is', a: 'response'}); 
     else 
     reject(error); 
    }}); 

在我的單元測試我有這樣一個測試:

mockedResponse = require('./fake/assertiveResponse.js'); 
mockedDependency  = require('./fake/dependency.js'); 

it('should throw error',function(){ 
    mockedDependency.setPromiseError(new Error('sorry, not today'); 
    myLibUnderTest.myFunctionUnderTest(someFakeRequest, 
             mockedResponse.get() 
             .expectedStatus(200), <--I´m forcing a failing test here! 
             mockedDependency); 
});  

但是......我斷言似乎是swalled由承諾,我得到一個測試通過與此控制檯輸出:

(node:1512) UnhandledPromiseRejectionWarning: Unhandled promise rejection 
(rejection id: 2): AssertionError: 500 === 200 

現在我甚至不確定我是否使用Promise正確的方式...任何幫助表示讚賞。

回答

0

您應該將承諾視爲表示您尚未擁有的數據的對象。

個人的大部分我的諾言經驗來自於使用jQuery的$.ajax方法,它實際上返回一個「承諾」或它自己的「推遲」對象:

$.ajax({ 
    url: "api.yourdomain.com/yourRoute", 
    success: function(data, textStatus, jqXHR){ 
      //this is the success callback 

    }, 
    error: function(jqXHR, textStatus, errorThrown){ 
     //this is the error callback 
    } 
    }); 

現在,讓我們說,你需要做出打電話來獲取一些客戶數據,並將該承諾傳遞給另一種方法。同樣,使用jQuery,你可以不喜歡

function getCustomerDataPromise(customerID){ 
    return $.ajax({ 
     url: "customerapi.yourdomain.com/customer/" + customerID, 
     success: function(data, textStatus, jqXHR){ 
      //this is the success callback 

     }, 
     error: function(jqXHR, textStatus, errorThrown){ 
     //this is the error callback 
     } 
    }); 
} 


function parseCustomerData(customerID){ 
    var customerDataPromise = getCustomerDataPromise(customerID); 

    $.when(customerDataPromise).done(
    function(customerDataResponse, responseText, responseObject){ 
     //this is the success callback of the promise 

    } 
); 

很酷的事情有關$.when是你實際上可以通過在那裏多的承諾,並將其解僱回調時,所有的人完成。

但是到你原來的問題,你可以模擬一個承諾,也使用jQuery,像這樣:

function makeMockedPromise(){ 
    var dummyPromise = $.Deferred(); 
    dummyPromise.resolve(
     { 
     mockedKey: "Is this mocked data?", 
     mockedKeyTwo: "You bet it is! A mocked response" 
     } 
    ); 
    return dummyPromise; 
} 

你可以在jQuery的文檔閱讀更多關於這一點:http://api.jquery.com/

+0

感謝您的回覆Garret。但我認爲這個問題會持續使用你的方法。我的理解是,在我嘲笑的迴應中,我的斷言拋出了一個例外,因此既不滿足也不拒絕承諾...... – Felipe

+0

不熟悉你的框架,所以不知道如何提供幫助。你不希望嘲笑的反應拋出異常嗎?如果是這樣的話,你在閱讀錯誤信息嗎?你需要定義一個錯誤回調嗎? –

0

不超熟悉Express,但看着你的代碼,是否只是一個錯字?

我看到this.expectedCode VS this.expectdCode

exports.expectedStatus = function(status){ 
    this.expectedCode = status; 
} 
exports.status = function(realStatus){ 
    this.expectdCode = realStatus; 
    return this; 
0

這完全是一個錯字,我通過移動我的斷言一個單獨的方法,並確保它的使用興農間諜呼叫解決的問題。這和使用settimeout來確保在我的斷言之前,所有的東西都會在最短的可接受時間內被執行。

可能不是最好的...但至少我有我的測試運行;) 感謝您的幫助。