如何在嵌套的promises中使用jasmine.clock setTimeout mock? (结果:Error: jasmine.DEFAULT_TIMEOUT_INTERVAL
)
订单在这里至关重要。
我需要测试必须在其中设置setTimeout的嵌套promises - 顺序问题。
我知道then
有点process.nextTick
(或setImmediate
),它超出了当前事件循环(这是此处的核心问题),但此knowledge
无法解决问题:)
我知道我可以将jasmine.clock().tick()
放在嵌套的promise中,但这是没有意义的,因为我在一些与lib相关的事件中测试了正确的顺序。
如何在茉莉花中测试这样的东西?任何想法?
it("should run setTimeout mock inside chained promises",(done)=>{
jasmine.clock().install();
let realOrder = [];
let ok1=new Promise((resolve,reject)=>{
resolve("ok");
}).then((ok)=>{// this is future - second level
let p=new Promise((resolve,reject)=>{
setTimeout(()=>{ // not fired up due to 'then' method
realOrder.push("1");
resolve("1");
},100);
});
//jasmine.clock().tick(101); //<- order is crucial here so I can't do that
return p;
});
let ok2=new Promise((resolve,reject)=>{
resolve("ok");
}).then((ok)=>{ // second level
let p=new Promise((resolve,reject)=>{
setTimeout(()=>{ // not fired up due to 'then' method
realOrder.push("2");
resolve("2");
},50);
});
//jasmine.clock().tick(51); //<- order is crucial here so I can't do that
return p;
});
jasmine.clock().tick(151);// we must go outside nested promise - we dont need to run tick inplace because order will change
Promise.all([ok1,ok2]).then((results)=>{
expect(results).toEqual(["1","2"]);
expect(realOrder).toEqual(["2","1"]);
done();
});
});
答案 0 :(得分:0)
对于那些遇到同样问题的人来说还好:
[更新]:我用fn https://www.npmjs.com/package/promiseloop
创建了一个npm包我创建了一个迭代then
级承诺执行的函数,并在每个级别运行一些函数,如jasmine.clock().tick()
,所以在每个级别上我们都会setTimeout
执行并捕获。< / p>
function promiseLoop(times,iterationFn,finalFn){
let current=0;
let p=Promise.resolve("ok");
function _loop(fn){
current++;
if(current<times){
p=p.then(()=>{
iterationFn(current);
_loop(finalFn);
});
}else{
p.then(()=>{
setImmediate(()=>{
finalFn();
});
});
}
}
_loop(finalFn);
}
times
是一个级别 - 我们想要通过then
级别的程度?
iterationFn
是将在每个then
级别上运行的功能
finalFn
是最后一级
根据问题,这是一个完整的例子:
it("should run setTimeout mock inside chained promises",(done)=>{
jasmine.clock().install();
let realOrder = [];
let ok1=new Promise((resolve,reject)=>{
resolve("ok");
}).then((ok)=>{ // second level
let p=new Promise((resolve,reject)=>{
setTimeout(()=>{ // not fired up due to 'then' method
realOrder.push("1");
resolve("1");
},100);
});
//jasmine.clock().tick(101); //<- order is crucial here so I can't do that
return p;
});
let ok2=new Promise((resolve,reject)=>{
resolve("ok");
}).then((ok)=>{ // second level
let p=new Promise((resolve,reject)=>{
setTimeout(()=>{ // not fired up due to 'then' method
realOrder.push("2");
resolve("2");
},50);
});
//jasmine.clock().tick(51); //<- order is crucial here so I can't do that
return p;
});
function iterationTick(){
jasmine.clock().tick(301);
// this will be executed on each promise level in our case second level
// that normally would not be catched by
// jasmine.clock().tick() because 'then' will be
// executed in the future and jasmine.clock().tick() is synchronous
// and will not see future setTimeouts
}
function finalTick(){
Promise.all([ok1,ok2]).then((results)=>{
expect(results).toEqual(["1","2"]);
expect(realOrder).toEqual(["2","1"]);
jasmine.clock().uninstall();
done();
});
//jasmine.clock().tick(301);
}
promiseLoop(2,iterationTick,finalTick);
});
其他例子
let testNr=0;
new Promise((resolve,reject)=>{
resolve("ok");
}).then(()=>{
// level 1
testNr++; // 1
}).then(()=>{
// level 2
testNr++; // 3
});
new Promise((resolve,reject)=>{
resolve("ok");
}).then(()=>{
// level 1
testNr++; // 2
}).then(()=>{
// level 2
testNr++; // 4
});
function each(currentLevel){
if(currentLevel==1){
expect(testNr).toEqual(2);
}else if(currentLevel==2){
expect(testNr).toEqual(4);
}
}
function final(){
expect(testNr).toEqual(4);
done();
}
promiseLoop(3,each,final);