Javascript 测试asyn调用会在节点JS中抛出未处理的承诺拒绝

Javascript 测试asyn调用会在节点JS中抛出未处理的承诺拒绝,javascript,node.js,unit-testing,promise,mocking,Javascript,Node.js,Unit Testing,Promise,Mocking,我正在单元测试这样一个Express函数: function(request,response,someDependency){ ... someDependency.doStuff(arg1,arg2) .then(function(someResponse){ response.status(200).send({body: someResponse}); }) .catch(function(error){ response.status(500

我正在单元测试这样一个Express函数:

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');
  });
}
function makeMockedPromise(){
  var dummyPromise = $.Deferred();
  dummyPromise.resolve(
      { 
        mockedKey: "Is this mocked data?",
        mockedKeyTwo: "You bet it is! A mocked response"
      }
    );
  return dummyPromise;
}
在我的单元测试(使用Mocha)中,我决定模拟我的响应,在响应中使用断言,并模拟我的依赖性:

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

现在我甚至不确定我是否以正确的方式使用了承诺……感谢您的帮助。

您应该将承诺视为表示您还没有的数据的对象

就我个人而言,我对承诺的大部分经验都来自于使用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

    }
  );
$最酷的一点是,当
的时候,你实际上可以在那里传递多个承诺,并在所有承诺都完成后让它发出回调

但是为了回答您最初的问题,您可以模拟一个承诺,也可以使用jQuery,如下所示:

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');
  });
}
function makeMockedPromise(){
  var dummyPromise = $.Deferred();
  dummyPromise.resolve(
      { 
        mockedKey: "Is this mocked data?",
        mockedKeyTwo: "You bet it is! A mocked response"
      }
    );
  return dummyPromise;
}

您可以在jQuery文档中阅读更多关于这方面的内容:

您应该将promise视为一个表示您还没有的数据的对象

就我个人而言,我对承诺的大部分经验都来自于使用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

    }
  );
$最酷的一点是,当
的时候,你实际上可以在那里传递多个承诺,并在所有承诺都完成后让它发出回调

但是为了回答您最初的问题,您可以模拟一个承诺,也可以使用jQuery,如下所示:

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');
  });
}
function makeMockedPromise(){
  var dummyPromise = $.Deferred();
  dummyPromise.resolve(
      { 
        mockedKey: "Is this mocked data?",
        mockedKeyTwo: "You bet it is! A mocked response"
      }
    );
  return dummyPromise;
}

您可以在jQuery文档中了解更多信息:

不太熟悉Express,但看看您的代码,是否只是输入错误

我看到这个.expectedCode这个.expectedCode

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

不太熟悉Express,但看看您的代码,是否只是输入错误

我看到这个.expectedCode这个.expectedCode

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

这完全是一个错误,我通过将断言转移到一个单独的方法并使用sinon spy确保其调用来解决这个问题。然后使用settimeout确保在断言之前以最短的可接受时间执行所有内容

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

这完全是一个错误,我通过将断言转移到一个单独的方法并确保使用sinon spy调用来解决这个问题。然后使用settimeout确保在断言之前以最短的可接受时间执行所有内容

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

谢谢你的回复。但我认为用你的方法这个问题会持续下去。我所理解的是,我在模拟响应中的断言抛出了一个异常,因此既不满足也不拒绝承诺……不熟悉您的框架,因此不确定如何提供帮助。您不希望模拟响应抛出异常吗?如果是这样,您是否正在阅读错误消息?您需要定义错误回调吗?谢谢您的回复。但我认为用你的方法这个问题会持续下去。我所理解的是,我在模拟响应中的断言抛出了一个异常,因此既不满足也不拒绝承诺……不熟悉您的框架,因此不确定如何提供帮助。您不希望模拟响应抛出异常吗?如果是这样,您是否正在阅读错误消息?是否需要定义错误回调?