3

我在一组 mocha 单元测试中使用了 before 块,并且在其中我正在迭代一组调用以从 REST API 获取信息。我正在使用 chai-http 来执行此操作。但是我遇到的问题是在我发出的一系列ndone()请求完成之前调用该方法。在 end 块中调用 done 会导致多次调用,但放在块之外意味着它在我真正完成之前就被调用了!这是一个前块的例子:done()

var flags = [];
var groups = [];

// This functions correctly 1 done() called at the end
before(function(done) {
    chai.request(server)
        .get('/groups')
        .end(function(err, res){
             groups = JSON.parse(res.text);
             done();
        });
    });

before(function(done) {
    groups.forEach(function(rec) {
        chai.request(server)
            .get('/groups/' + rec.KEYWORD_GROUP_ID + '/groupflags')
            .end(function(res, err) {
                Array.prototype.push.apply(flags, JSON.parse(res.text));
                // A done() here gets called n times
                });
        // But here it's called before the requests all end
        done();
        });

有没有办法检测所有这些请求何时完成,然后我可以调用一个done()来确保我的测试只在正确的上下文设置下执行?

4

2 回答 2

3

您可以尝试使用async.whilst(). 计算 groups.length 的计数器,然后done()在回调中命中。函数文档链接:( http://caolan.github.io/async/docs.html#whilst )

就像是...

let counter = 0;
async.whilst(
    () => {
        // Test if we have processed all records
        return counter < groups.length;
    },
    (callback) => {
        let rec = groups[counter++]; // Sorry Douglas
        chai.request(server)
            .get('/groups/' + rec.KEYWORD_GROUP_ID + '/groupflags')
            .end(function (res, err) {
                Array.prototype.push.apply(flags, JSON.parse(res.text));
                callback(null, counter);
            });
    },
    (err) => {
        assert(!err, err);
        done();
    }
);
于 2017-04-25T14:50:24.117 回答
2

正如亚历克斯在这里所要求的那样,我最初的解决方案是:

before('delete keywords in a group', function(done) {
    var count = 0;
    var length = groups.length;

    if (length === 0) {done();}

    groups.forEach(function (rec) {
        chai.request(server)
            .delete('/keywords/' + rec.id)
            .end(function (err, res) {
                if (err) {
                    console.error('Delete keywords err: ' + err.message);
                    this.skip();
                } else {
                    count++;
                    if (count === length) {done();}
                    }
            });
        });
    });

这似乎有效,但我认为对于任何更复杂的情况(例如级联样式删除),异步库提供了更优雅和可靠的解决方案。因此,它更适合一般情况。

于 2017-05-04T05:57:55.710 回答