2017-07-03 48 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来确保在我的断言之前,所有的东西都会在最短的可接受时间内被执行。

可能不是最好的...但至少我有我的测试运行;) 感谢您的帮助。