当订单有问题时,如何在嵌套的promises中使用jasmine clock(setTimeout)? (jasmine.DEFAULT_TIMEOUT_INTERVAL错误)

时间:2017-02-24 19:28:33

标签: javascript node.js testing mocking jasmine

如何在嵌套的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();
      });
  });

1 个答案:

答案 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);