Javascript 承诺:单元测试一个递归方法,在队列中一个接一个地激发承诺

Javascript 承诺:单元测试一个递归方法,在队列中一个接一个地激发承诺,javascript,jasmine,promise,Javascript,Jasmine,Promise,我的项目中有一个方法,它接收一组承诺返回方法。当第一个完成时,它会移动到下一个,以此类推。我很难想出如何对这个方法进行单元测试 fireAllBatches: function (batchQueue, resolve, reject) { if (batchQueue.length) { var batch = batchQueue.pop(); // this returns a promise googleCalendarServi

我的项目中有一个方法,它接收一组承诺返回方法。当第一个完成时,它会移动到下一个,以此类推。我很难想出如何对这个方法进行单元测试

fireAllBatches: function (batchQueue, resolve, reject) {
    if (batchQueue.length) {
        var batch = batchQueue.pop();

        // this returns a promise
        googleCalendarService.fireBatch(batch)
            .then(function (results) {                      
                // when done fires the next one
                this.fireAllBatches(batchQueue, resolve, reject);

            }.bind(this)).catch(reject);
     } else {
        console.log('resolving firing of batches.');
        resolve();
     }
}
这就是测试:

it('fireAllBatches should call fireBatch as many times as the number of the batches', function () {
    spyOn(mockGoogleCalendarService, "fireBatch").and.returnValue(q.when({}));

    datalayerObject.fireAllBatches([1, 2, 3, 4, 5, 6]);

    expect(mockGoogleCalendarService.fireBatch).toHaveBeenCalled();
    expect(mockGoogleCalendarService.fireBatch.calls.count()).toBe(6);

});
更新

经过调查和阅读答案。我能够将递归方法转换为:

fireAllBatches: function (batchQueue, resolve, reject) {
    var methodArray = _.map(batchQueue, function (batch) {
        return function () {
            console.log('firing batch');
            return googleCalendarService.fireBatch(batch)
        }
    });

    var resolvedPromise = $q.when(true);

    methodArray.reduce(function(cur, next) {
        return cur.then(next);
    }, resolvedPromise).then(resolve).catch(reject);

}

但是,我不确定它是否能正确捕获错误。

这不是关于单元测试的具体答案。但是,如果您使用ES6,您可以按照以下方法避免递归,这样可以简化测试:

batchQueue.reduce( (chain,batch) => {
    return chain.then(googleCalendarService.fireBatch(batch))
}, Promise.resolve(null)).then(resolve).catch(reject);

我会模拟或删除
googleCalendarService.fireBatch()
函数,这样您就可以验证调用它的内容,然后就可以使用spy来解析和拒绝参数

以下是我要测试的内容:

  • (可选)考虑<代码> BoqQueue/COD>空/未定义的情况。
  • 如果
    batchQueue
    为空,则应立即调用
    resolve
  • 它应该在第一批中调用一次
    googleCalendarService.fireBatch
    stub,然后如果您在队列中传递一个批,则调用resolve
  • 对于2个批次的队列,它应该调用
    googleCalendarService.fireBatch
    存根两次,并调用
    resolve
    spy一次
  • 测试
    googleCalendarService.fireBatch
    函数是否引发调用
    reject
    spy的错误

你也可以考虑额外的测试。

伙计,很抱歉这么苛刻,但在编写测试之前,你需要先做一些值得测试的事情。第二次尝试看起来比第一次更好,但我认为您不希望在减少之前绘制地图。尝试
batchQueue.reduce(…)
。起初,我在reduce中一次完成了这一切。代码很短,但我不知道它在做什么。我发现有时短高效代码的可读性不如表达性代码。既然没有真正的表现,为什么不分两个阶段来做呢。你不同意吗?伙计,我评论背后的理由如下:从问题的第一个代码块,我知道
googleCalendarService.fireBatch(…)
返回一个承诺;因此,在第二个代码块中,
\.map()
创建一个承诺数组,由
methodArray.reduce(…)
进一步处理;因此,
next
var是一个承诺,而
cur.then(next)
将失败,因为
.then()
需要一个函数,而不是承诺。S.McCrohan下面的观点几乎是正确的(不过,正如他承认的那样,这更多的是一个评论而不是一个答案)。