使用sinon.js计时器测试node.js中的async.waterfall

时间:2016-09-16 16:22:09

标签: javascript node.js unit-testing sinon async.js

我有以下希望测试的函数,其中大量使用async.js:

MyClass.prototype.pipeline = function(arg1, arg2) {
    ...
    async.waterfall([
        async.apply(self.a.f.bind(self.a), arg1, arg2),
        function(data, callback) {
            async.each(data, function(d, callback) {
                async.waterfall([
                    async.apply(self.b.f.bind(self.b), d),
                    self.c.f.bind(self.c),
                    self.d.f.bind(self.d),
                    self.e.f.bind(self.f)
                ], function(err, results) {
                    if (err) {
                        ...
                    }
                    callback();
                });
            }, function(err) {
                callback(err, data);
            });
        }
    ], function (err, result) {
        ...
    });
};

现在我知道我可以把很多在这里发生的事情分开来分离各种功能,但它是在前一个完成后将数据相互传递的简化动作的管道,所以我希望保持它像这样,例如将函数function(data, callback) {...}与BCDEpipeline这样的名称分开。 无论如何,我的问题是我根据第一个async.waterfall()完成函数的完成回调做了一些断言,问题是它后来被调用(延迟),即使我存在a,b,c,d和e函数已经让他们立即产生下一个回调。请注意,我不能只是存根async.waterfall()并使其完成回调,因为我将留下未经测试的关键代码分支(async.each()的内部完成回调和第二个async.waterfall()。 我尝试使用sinon假定时器并在调用this.clock.tick(0);函数之后使用MyClass.prototype.pipeline(),如下所示:

var obj = new MyClass();
obj.pipeline(5, 3);
this.clock.tick(0);
/* assertions */
...

但即便如此,在调用任何完成函数之前,部分正在被执行。我试图深入研究异步库代码,看看它是如何调用它的完成函数的,这太令人头疼了,我无法弄清楚为什么即使完成的回调调用都是延迟的并且与sinon一起假定时器,我的断言代码仍在执行。 如果我使用一些嵌套的setImmediate()调用它可以正常工作,但这是解决此问题的最差解决方案。

2 个答案:

答案 0 :(得分:0)

你遗漏了很多东西,所以很难分辨出这应该做些什么。老实说,这听起来像是噪音,虽然这不是你的错。

如果你实际上并不需要并行执行大量的IO,那么这就是我的建议。切换到ES2017和babel。使用带有@autobind的类或类似的语法:

def contin():
    con = input("Do you want to continue (Y/N):")

    if con == 'y' or con == 'Y':
        return menu()
    else:

然后使用class Test { constructor(testB) { this.testB = testB; } fuzz = async x => x+1; async foo = (bar) => { try { const result = await this.testB.blah(bar); return await this.fuzz(result); } catch (e) { console.error(e); return null; } } async fizz = (bars) => await Promise.all(bars.map(this.foo)); } 进行测试。通过这种方式,您可以通过循环和异步测试来处理异步函数的基本流程(ava),以及您的方法' await将始终指向您的实例。

答案 1 :(得分:0)

好吧,根据以下问题我觉得这是旧版本的错误: https://github.com/caolan/async/issues/609
https://github.com/caolan/async/issues/106

虽然它们已经很老了,而且我使用的是较新版本,但我刚刚更新了我的依赖项,现在它正常运行。