2016-09-16 18 views
1

我已经被测试了以下的功能,我想这在它大量使用async.js:测试async.waterfall与sinon.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假定时器,我的断言代码仍然执行f IRST。 如果我使用一些嵌套的setImmediate()调用它可以正常工作,但这是这个问题最糟糕的解决方案。

+0

什么是'.bind'?这是你的实际代码还是你缩短了这个问题的东西? – clay

+0

@clay我使用bind来调用使上下文成为实例本身,这是从不相关的部分中剥离出来的代码,无论您看到什么,......都是不相关的部分。所有的名字都是虚构的(a,b,c,d,e,f,arg1,arg2等)。 – Jorayen

回答

0

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

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

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)通过循环和异步测试处理异步函数的基本流程,并且您的方法的this将始终指向您的实例。

+0

不幸的是我使用了很多的I/O,现在切换到babel现在工作太多了,我现在买不起 – Jorayen

+0

好吧,只是为了澄清我的意思是I/O并行,因为它好像你一次试图做一个I/O,而不是同时做一个I/O。 –

+0

哦,我看到你有一个async.each在那里是平行的部分。我会用Promise.all中的try catch来使它成为一个单独的函数。无论如何,也许下线你可以调查,当你有时间babel等..祝你好运。 –