'it'块执行多次,直到在Jasmine 2.0中调用'done'

时间:2015-05-21 14:09:55

标签: javascript karma-jasmine

我正在Jasmine 2.0中创建一个测试用例

    describe("TestCase", function(){

        var originalTimeout=0;

        beforeEach(function(){
            originalTimeout=jasmine.DEFAULT_TIMEOUT_INTERVAL;
            jasmine.DEFAULT_TIMEOUT_INTERVAL=10000;
        });

        afterEach(function(){
            jasmine.DEFAULT_TIMEOUT_INTERVAL=originalTimeout;
        });

        it("check timeout", function(done){
            var startTime=new Date().getTime() / 1000; //line 15
            setTimeout(function(){
                var currentTime=new Date().getTime() / 1000;
                expect(currentTime).toBeGreaterThan(startTime);
                done();
            },5000);
        });
   });

在调试它时,我注意到如果我们在第15行保留一个断点,它会一次又一次地被击中,直到调用setTimeout完成为止。对这种行为有什么解释吗?这种行为导致一次又一次地执行相同的测试。

1 个答案:

答案 0 :(得分:0)

好的,我已经很好地了解了Jasmine的来源,我发现在这个领域1.x - 2.x - master之间已经做了很多工作。

但是,我找不到一个循环,它会一次又一次地调用它,等待done()被调用。

以下是相关代码from 2.0

  if (fn.length > 0) {
    attempt(function() { fn.call(self, function() {  self.run(fns, index + 1) }) });
  } else {
    attempt(function() { fn.call(self); });
    self.run(fns, index + 1);
  } 

  function attempt(fn) {
    try {
      fn();
    } catch (e) {
      self.onException(e);
      if (!self.catchingExceptions()) {
        //TODO: set a var when we catch an exception and
        //use a finally block to close the loop in a nice way..
        throw e;
      }
    }
  }

您可以看到上面的代码检查是否存在done参数fn.length > 0,然后创建done作为执行下一个测试用例的调用。

这类似于代码on master(但是,master已经发生了很大变化):

    for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
      var queueableFn = queueableFns[iterativeIndex];
      if (queueableFn.fn.length > 0) {
        attemptAsync(queueableFn);
        return;
      } else {
        attemptSync(queueableFn);
      }
    }

    function attemptAsync(queueableFn) {
      var clearTimeout = function () {
          Function.prototype.apply.apply(self.timeout.clearTimeout, [j$.getGlobal(), [timeoutId]]);
        },
        next = once(function () {
          clearTimeout(timeoutId);
          self.run(queueableFns, iterativeIndex + 1);
        }),
        timeoutId;

      next.fail = function() {
        self.fail.apply(null, arguments);
        next();
      };

      if (queueableFn.timeout) {
        timeoutId = Function.prototype.apply.apply(self.timeout.setTimeout, [j$.getGlobal(), [function() {
          var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.');
          onException(error, queueableFn);
          next();
        }, queueableFn.timeout()]]);
      }

      try {
        queueableFn.fn.call(self.userContext, next);
      } catch (e) {
        handleException(e, queueableFn);
        next();
      }
    }

除了一些变化之外,这大致相似。首先,代码在异步调用周围添加另一个setTimeout(并添加超时错误消息)。其次,对下一个测试用例的调用也包含在对once

的调用中
  function once(fn) {
    var called = false;
    return function() {
      if (!called) {
        called = true;
        fn();
      }
    };
  }

once函数确保仅调用一次测试。这让我觉得2.0中有一个错误(我没看到),一次又一次地调用测试。

虽然没有定论,但这可能会给你一些想法。它可能是IDE问题而不是Jasmine问题。

无论如何,我希望这会有所帮助。