【问题标题】:Is Jasmine's beforeEach synchronous?Jasmine 的 beforeEach 是同步的吗?
【发布时间】:2015-07-18 14:59:16
【问题描述】:

如果您有多个beforeEach,它们会一直一个接一个地运行吗?

beforeEach(function() {});
beforeEach(function() {});
beforeEach(function() {});
beforeEach(function() {});
beforeEach(function() {});

看来他们会的。我尝试用我的代码对其进行测试:

describe('Directive: Statement', function() {
  var el, scope, statements;

  beforeEach(module('simulatedSelves'));
  beforeEach(module('templates'));
  beforeEach(inject(function($compile, $rootScope) {
    console.log(1);
    scope = $rootScope.$new();

    statements = [];
    scope.statement = {
      text: 'test',
      arr: []
    };
    scope.statement.parent = statements;
    statements.push(scope.statement);

    el = angular.element('<statement statement=statement></statement>');
    $compile(el)(scope);
    scope.$digest();
  }));
  beforeEach(function() {
    var counter = 0;
    console.log(2);
    for (var i = 0; i < 1000000; i++) {
      counter++;
    }
    console.log(counter);
  });
  beforeEach(function() {
    console.log(3);
  });

  it('test statement has correct properties', function() {
    // stuff
  });
});

它记录:

1
2
1000000
3

由于beforeEach 和长for 循环在记录3 之前记录其内容,我认为beforeEach 同步运行。这是真的吗?

【问题讨论】:

    标签: javascript jasmine


    【解决方案1】:

    是的,所有beforeEachs 都将按照您定义的顺序执行。

    如果你深入 Jasmine,你最终会到达this definition

    Suite.prototype.beforeEach = function(fn) {
      this.beforeFns.unshift(fn);
    };
    

    当您添加describes 时,Suites 会生成并嵌套。每个Suite 都使用this.beforeFns = [] 进行初始化,如您所见,已添加到其中。请注意,unshift 添加到数组的左侧,因此您希望稍后定义的 beforeEachs 首先运行。那是 fixed later,当 Jasmine 走到子套件的父母时,收集所有 beforeEach 列表,然后将它们反转以按照您想要的顺序运行。

    var beforeAndAfterFns = function(suite) {
      return function() {
        var befores = [],
          afters = [];
    
        while(suite) {
          befores = befores.concat(suite.beforeFns);
          afters = afters.concat(suite.afterFns);
    
          suite = suite.parentSuite;
        }
    
        return {
          befores: befores.reverse(),
          afters: afters
        };
      };
    };
    

    作为Danpoints out,到目前为止,我们假设您的所有beforeEachs 都是同步的。从 Jasmine 2 开始,您可以像这样设置异步 beforeEachs:

    beforeEach(function(done) {
      setTimeout(function() {
        console.log('Async');
        done();
      }, 1000)
    });
    

    在运行时,Jasmine 向您发送done 函数并异步执行if your function takes an argument。 (Function.length 返回函数期望的参数数量)。

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

    attemptAsyncQueueRunner 移动到下一个beforeEach 钩子之前等待您调用done(),所以订购仍然有效!很整洁。

    describe('beforeEach', function() {
      var data = null;
    
      beforeEach(function() { data = []; });
      beforeEach(function() { data.push(1); });
      beforeEach(function(done) {
        setTimeout(function() {
          data.push('Async');
          done();
        }, 1000);
      });
      beforeEach(function() { data.push(2); });
      beforeEach(function() { data.push(3); });
    
      it('runs in order', function(){
        expect(data).toEqual([1, 'Async', 2, 3]);
      });
    });
    

    【讨论】:

    • Jasmine 也支持异步 beforeEach 与 promises 和回调,所以我不认为它是那么简单的尝试
    • 很好,现在我正在深入了解QueueRunner 的工作原理。
    • @DanPantry 更新了异步行为,我学到了很多东西。谢谢!
    猜你喜欢
    • 2018-08-13
    • 2014-10-25
    • 1970-01-01
    • 2013-07-24
    • 2015-08-19
    • 2012-05-18
    • 1970-01-01
    • 2020-05-26
    • 1970-01-01
    相关资源
    最近更新 更多