如何在NodeJS中testingrecursion调用的函数?

我有一个ES6 / 7编写的反复函数,由babel转换。 我有一个循环函数创build,检查是否有用户文件,使用mongoose。

// Keep checking if there is a user, if there is let execution continue export async function checkIfUserExists(){ let user = await User.findOneAsync({}); // if there is no user delay one minute and check again if(user === null){ await delay(1000 * 60 * 1) return checkIfUserExists() } else { // otherwise, if there a user, let the execution move on return true } } 

如果没有用户,我正在使用delay库来延迟执行一分钟,这个函数被recursion地调用。

这允许停止执行整个function,直到find用户:

 async function overallFunction(){ await checkIfUserExists() // more logic } 

else分支很容易生成testing。 如何为validationrecursion正常工作的if分支创build一个testing?

目前,我已经在testing期间用proxyquirereplace了延迟方法,将它作为一个自定义的延迟函数,只是返回一个值。 在这一点上,我可以改变代码看起来像这样:

 // Keep checking if there is a user, if there is let execution continue export async function checkIfUserExists(){ let user = await User.findOneAsync({}); // if there is no user delay one minute and check again if(user === null){ let testing = await delay(1000 * 60 * 1) if (testing) return false return checkIfUserExists() } else { // otherwise, if there a user, let the execution move on return } } 

问题在于源代码正在被改变以适应testing。 有更好,更清洁的解决scheme吗?

我不知道为什么你想要使用recursion解决scheme而不是迭代解决scheme – 但是如果没有其他原因而不是迭代地编写它,可能会更容易。

  do{ let user = await User.findOneAsync({}); // if there is no user delay one minute and check again if(user === null){ await delay(1000 * 60 * 1); } else{ return true; } }while (!user); 

没有通过翻译testing或运行,但你明白了。

然后在您的testing模式 – 只提供一个testing用户。 因为您可能需要编写testing,无论如何都要使用对用户的引用。

有几个库可以用来testing时间相关的事件。 据我所知最常见的解决scheme是Lolex – https://github.com/sinonjs/lolex,Sinon项目的早期部分。 Lolex的问题在于它同步地转发定时器,因此忽略了诸如本地节点承诺或process.nextTick (尽pipe它伪造setImmediate正确)的事件 – 因此你可能会遇到一些讨厌的问题。 要小心外部库 – 例如, bluebirdcaching初始setImmediate ,所以你需要以某种方式手动处理它。

不同的select是Zurvan – https://github.com/Lewerow/zurvan (免责声明:我写的)。 这比Lolex更难处理,因为它大量使用promise,但是在微队列任务( process.nextTick ,native Promise )的存在下正常运行,并且具有蓝鸟的内置兼容性选项。

这两个库允许您在arbirary长度上过期与时间有关的事件,也可以覆盖Date实例(zurvan也覆盖process.uptimeprocess.hrtime )。 如果您在testing中执行实际的asynchronousIO,则它们都不是安全的。

我已经写了一个如何在这里testingrecursion调用函数的例子:

https://jsfiddle.net/Fresh/qppprz20/

这个testing使用了Sinon javascripttesting库。 您可以在第n次调用时设置存根的行为,因此您可以模拟何时没有用户返回,然后在用户返回时

 // Stub the method behaviour using Sinon javascript framework var user = new User(); var userStub = sinon.stub(user, 'findOneAsync'); userStub.onFirstCall().returns(null); userStub.onSecondCall().returns({}); 

因此onFirstCall模拟第一个呼叫和onSecondCallrecursion调用。

请注意,在完整的例子中,我简化了checkIfUserExists,但是相同的testing前提将适用于您的完整方法。 另外请注意,你还需要存根延迟方法。