如何在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
正确)的事件 – 因此你可能会遇到一些讨厌的问题。 要小心外部库 – 例如, bluebird
caching初始setImmediate
,所以你需要以某种方式手动处理它。
不同的select是Zurvan – https://github.com/Lewerow/zurvan (免责声明:我写的)。 这比Lolex更难处理,因为它大量使用promise,但是在微队列任务( process.nextTick
,native Promise
)的存在下正常运行,并且具有蓝鸟的内置兼容性选项。
这两个库允许您在arbirary长度上过期与时间有关的事件,也可以覆盖Date
实例(zurvan也覆盖process.uptime
和process.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前提将适用于您的完整方法。 另外请注意,你还需要存根延迟方法。