'this' 仅在组件集成测试中未定义

'this' undefined only from component integration test

这是一个 Ember 组件,在某些时候需要 this

export default Component.extend({
  filteredSubs: computed.filter('model.subs', function() {
    // this will always return true in development http://localhost:4200/dummy
    // but will always return false in test because 'this' becomes undefined
    return this;
  })
});

DummySub:

具有一对多关系
export default Model.extend({
  subs: hasMany('sub')
});

export default Model.extend({
  dummy: belongsTo('dummy')
});

此测试失败但不应该:

test('it renders', function(assert) {
  let dummy = server.create('dummy');
  server.create('sub', { dummy });

  this.set('dummy', dummy);
  this.render(hbs`{{show-dummy model=dummy}}`);

  assert.equal(this.$().text().trim(), 'Hi! There are 1 sub-dummies');
});

not ok 13 Chrome 63.0 - Integration | Component | show dummy: it renders

actual: Hi! There are 0 sub-dummies

expected: Hi! There are 1 sub-dummies

你的问题来自一系列不幸的错误假设。

你的第一个假设是Ember.computed.filter里面的this应该是对应的对象。我不是 100% 确定这是有记录的行为,我个人也不会依赖它。如果您需要 this 的完全访问权限,我会使用简单的 Ember.computed.

但是你的主要错误是在你的测试中。这也解释了为什么你只在测试中出现这个问题。您直接使用海市蜃楼模型作为组件的 model

let dummy = server.create('dummy');
server.create('sub', {
  dummy
});

this.set('dummy', dummy);

this.render(hbs`{{show-dummy model=dummy}}`);

这里假设海市蜃楼模型 server.create 的结果在某些方面类似于 ember-data 模型。 不是! 事实上,海市蜃楼模型甚至不是 ember 物体!所以你不能在它上面使用 .get.set,或者你在你的模型上定义的任何东西,并且绝对不应该将它用作组件测试的模型。相反,您应该使用 mirage 作为 ember-data 模型的数据源。

如果您的模型是海市蜃楼模型,为什么 this 未定义的问题导致 this line in ember-cli-mirage:

filter(f) {
  let filteredModels = this.models.filter(f);

  return new Collection(this.modelName, filteredModels);
}

this-上下文丢失的地方。基本上,海市蜃楼覆盖了他们自定义的类数组结构上的 .filter 函数,并且不确保保留 this-context.