如何在Promise.all()上测试catch块?

时间:2016-11-30 06:22:35

标签: javascript unit-testing promise mocha chai

得到这段代码:

//Waiting until all records are inserted to DB
Promise.all(promises).then(function(err){   
    context.succeed({ valid: true, succeedRecords:succeedRecords, failedRecords:failedRecords });
    //Log
    console.log("Lambda function is finished - Successfully added records: " + succeedRecords.length + ",  Failed records: " + 
        failedRecords.length + "  -  Total processed records: " + event.Records.length);   
})
.catch(function (err) {
    if (err) {
        var msg = "Got error from Promise.all(), Error: " + err;
        console.log(msg);
        context.fail({ valid: false, message: msg });
    }
});

我需要知道如何使用mocha测试catch块?

1 个答案:

答案 0 :(得分:0)

假设您只想检查Promise.all是否失败,代码会更简单:

//Waiting until all records are inserted to DB
return Promise.all(promises).then(function(err){   
  context.succeed({ valid: true, succeedRecords:succeedRecords, failedRecords:failedRecords });
  //Log
  console.log("Lambda function is finished - Successfully added records: " + succeedRecords.length + ",  Failed records: " + 
    failedRecords.length + "  -  Total processed records: " + event.Records.length);   
});
在这种情况下,

mocha会向返回的promise附加catch,如果被调用则会失败。

在某些情况下,您希望处理错误情况,执行一些检查并仅在特定情况下失败:

//Waiting until all records are inserted to DB
return Promise.all(promises).then(function(err){   
  context.succeed({ valid: true, succeedRecords:succeedRecords, failedRecords:failedRecords });
  //Log
  console.log("Lambda function is finished - Successfully added records: " + succeedRecords.length + ",  Failed records: " + 
    failedRecords.length + "  -  Total processed records: " + event.Records.length);   
})
.catch(function (err) {
  var msg = "Got error from Promise.all(), Error: " + err;
  console.log(msg);
  // ... do some stuff here
  context.fail({ valid: false, message: msg });

  // add an expectation here to check if the error message is correct
  // If the error message is "this error" the test passes, otherwise it will fail
  expect(err).to.be.eql('this error');
});

详细

我会退后一步,试着详细解释它的工作原理。 假设你有一个拒绝承诺的测试:

// your code
it('rejects', () => {

  return Promise.reject();

});

此测试将失败,因为mocha将执行以下操作(实际代码为here):

// this is pseudo code for the mocha insides
var result = fn.call(ctx);
if (result && result.then) {

  result
    .then(function successCase() {
      // all fine here
      done();
    })
    .catch(function errorCase(reason) {
      done(reason);
    });
  }

因此,您返回的承诺将与.then.catch链接,并且将传递两个回调:一个用于成功(使测试通过),一个用于错误(使测试失败) )。

在上述拒绝案件中,会发生以下情况:

  // mocha code (I've just replaced the function call with its result)
  var result = Promise.reject();
  if(result && result.then){
    result.then(function successCase() {
      // this is not called!
      done();
    })
    .catch(function errorCase(reason) {
      // it will land here!
      done(reason);
    } );
  }

在OP问题的代码中,Promise可能会出错并且该错误将被捕获:

Promise.reject()
  .catch( function( err ){
    var msg = "Got error from Promise.all(), Error: " + err;
    console.log(msg);
    context.fail({ valid: false, message: msg });
  }); <-- what is the output here?

以上是您的Promise.all拒绝并且您在测试中捕获它的情况。 catch的结果是......成功!

// your code
Promise.reject()
  .catch( function( err ){
    var msg = "Got error from Promise.all(), Error: " + err;
    console.log(msg);
    context.fail({ valid: false, message: msg });
  })

  // mocha code
  .then(function successCase() {
    // this is called! (and make the test pass)
    done();
  })
  .catch(function errorCase(reason) {
    // it will NOT call this
    done(reason);
  });

现在,说你想要拒绝承诺,捕获错误然后测试一些东西(可能是错误信息?其他一些选项?等等......)。鉴于上面的代码你怎么做?很容易,你以某种方式抛出错误。一种方法可能是显式抛出错误,或者您可以使用断言(失败的断言会引发错误)。

// your code
Promise.reject()
  .catch( function( err ){
    var msg = "Got error from Promise.all(), Error: " + err;
    console.log(msg);
    context.fail({ valid: false, message: msg });

    // It will throw!
    expect(true).to.be(false);

    // or you can go vanilla
    throw Error("I don't like Errors!");
  })

  // mocha code
  .then(function successCase() {
    // this is NOT called!
    done();
  })
  .catch(function errorCase(reason) {
    // it will call this! (and make the test fail)
    done(reason);
  });