1

当用 Jasmine 测试反应性时,一些 Tracker 计算开始以一种非常有趣的方式表现:恰好一半的计算是反应性的,另一半不是。

我为测试这种行为所做的如下:

//In a describe block
var foo = new ReactiveVar(false);

it('should react to the changes of foo (1)', function(done) {
  Tracker.autorun(function observeFoo(fooComputation) {
    var fooValue = foo.get();
    console.log('foo in its computation is', fooValue);
    if ( fooValue === true ) {
      fooComputation.stop();
      done();
    }
  });

  setTimeout(function setFoo() {
    foo.set(true);
  }, 100);
});

所以基本上:

  1. 将反应式初始化foofalse.
  2. 开始跟踪它,等待它到达,true以便将测试声明为done().
  3. 使用超时来foo.set(true)解决测试。
  4. 停止此计算,因为不再需要它。

现在,让我们用不同的变量做同样的事情:

var foo = new ReactiveVar(false),
    bar = new ReactiveVar(false);

it('should react to the changes of foo (1)', function(done) { /* ... */ });

it('should react to the changes of bar (2)', function(done) {
  Tracker.autorun(function observeBar(barComputation) {
    var barValue = bar.get();
    console.log('bar in its computation is', barValue);
    if ( barValue === true ) {
      barComputation.stop();
      done();
    }
  });

  setTimeout(function setBar() {
    bar.set(true);
  }, 100);
});

这就是乐趣的开始。虽然这个测试是相同的代码但名称不同,并且具有完全相同的编写逻辑,但它失败了,因为计算跟踪栏永远不会重新运行

console.log很好地展示了这一点:

foo 在它的计算中是:false
foo 在它的计算中是:true - 反应性开始了!
其计算中的 bar 是:false
[Nothing]

虽然很清楚 for 的计算foo被重新运行,因此其测试已完成,但 for 的计算bar永远不会失效,因此测试失败。

然而,这并不止于此。如果我们为一个新的反应变量(例如 )添加第三个测试用例baz并遵循与之前相同的过程(与其他变量一起初始化它,在同一函数的末尾添加测试describe),那么它就可以完美地工作了!

var foo = new ReactiveVar(false),
    bar = new ReactiveVar(false),
    baz = new ReactiveVar(false);

it('should react to the changes of foo (1)', function(done) { /* ... */ });
it('should react to the changes of bar (2)', function(done) { /* ... */ });

it('should react to the changes of baz (3)', function(done) { /* ... */ });

这里测试(1)成功,测试(2)失败,测试(3)成功。

现在,如果我们添加第四个测试,cat例如,按照相同的过程添加一个新的测试......那么测试(4)将失败并显示以下日志。

foo 在它的计算中是false
foo 在它的计算中是true
bar 在它的计算中是false bar 没有重新运行并且失败
baz 在它的计算中是false
baz 在它的计算中是true
cat 在它的计算中是false cat 没有重新运行并且失败
[Nothing]

foo并且baz已经对,而不是bar和做出了反应cat

我已经和另外两个(第五个和第六个)一起做了,同样的结果:(5)成功,(6)失败。
“奇数”测试成功,“偶数”测试失败。

完整复制代码:

describe('Tracker usage with Jasmine', function() {
  var foo = new ReactiveVar(false),
      bar = new ReactiveVar(false),
      baz = new ReactiveVar(false),
      cat = new ReactiveVar(false),
      pup = new ReactiveVar(false),
      elf = new ReactiveVar(false);

  it('should react to the changes of foo (1)', function(done) {
    Tracker.autorun(function observeFoo(fooComputation) {
      var fooValue = foo.get();
      console.log('foo in its computation is', fooValue);
      if ( fooValue === true ) {
        fooComputation.stop();
        done();
      }
    });

    setTimeout(function setFoo() {
      foo.set(true);
    }, 100);
  });

  it('should react to the changes of bar (2)', function(done) {
    Tracker.autorun(function observeBar(barComputation) {
      var barValue = bar.get();
      console.log('bar in its computation is', barValue);
      if ( barValue === true ) {
        barComputation.stop();
        done();
      }
    });

    setTimeout(function setBar() {
      bar.set(true);
    }, 100);
  });

  it('should react to the changes of baz (3)', function(done) {
    Tracker.autorun(function observeBaz(bazComputation) {
      var bazValue = baz.get();
      console.log('baz in its computation is', bazValue);
      if ( bazValue === true ) {
        bazComputation.stop();
        done();
      }
    });

    setTimeout(function setBaz() {
      baz.set(true);
    }, 100);
  });

  it('should react to the changes of cat (4)', function(done) {
    Tracker.autorun(function observeCat(catComputation) {
      var catValue = cat.get();
      console.log('cat in its computation is', catValue);
      if ( catValue === true ) {
        catComputation.stop();
        done();
      }
    });

    setTimeout(function setCat() {
      cat.set(true);
    }, 100);
  });

  it('should react to the changes of pup (5)', function(done) {
    Tracker.autorun(function observePup(pupComputation) {
      var pupValue = pup.get();
      console.log('pup in its computation is', pupValue);
      if ( pupValue === true ) {
        pupComputation.stop();
        done();
      }
    });

    setTimeout(function setPup() {
      pup.set(true);
    }, 100);
  });

  it('should react to the changes of elf (6)', function(done) {
    Tracker.autorun(function observeElf(elfComputation) {
      var elfValue = elf.get();
      console.log('elf in its computation is', elfValue);
      if ( elfValue === true ) {
        elfComputation.stop();
        done();
      }
    });

    setTimeout(function setElf() {
      elf.set(true);
    }, 100);
  });
});

为什么会这样?
我怎样才能解决这个问题,同时将所有这些反应变量保持在同一个describe函数中?


我试图添加嵌套describe函数但没有成功。
在自己不相关的describe函数中隔离测试时,这个问题神奇地消失了,请不要这样回答。

4

0 回答 0