Javascript 余烬组件测试——如何对组件进行单元测试';当它不';不调用外部操作?
我对Ember有些陌生,正在尝试测试寻呼机组件。简化组件如下所示:Javascript 余烬组件测试——如何对组件进行单元测试';当它不';不调用外部操作?,javascript,testing,ember.js,ember-testing,Javascript,Testing,Ember.js,Ember Testing,我对Ember有些陌生,正在尝试测试寻呼机组件。简化组件如下所示: export default Ember.Component.extend({ index: 0, actions: { next() { this.incrementProperty('index'); } } }); test('next should increment the index by 1', function (assert) {
export default Ember.Component.extend({
index: 0,
actions: {
next() {
this.incrementProperty('index');
}
}
});
test('next should increment the index by 1', function (assert) {
const component = this.subject();
assert.equal(component.get('index'), 0, 'Index should be 0');
component.get('actions').next();
assert.equal(component.get('index'), 1, 'index should be 1');
});
我试图测试next()操作是否确实按照预期增加了index属性。我编写了一个单元测试,如下所示:
export default Ember.Component.extend({
index: 0,
actions: {
next() {
this.incrementProperty('index');
}
}
});
test('next should increment the index by 1', function (assert) {
const component = this.subject();
assert.equal(component.get('index'), 0, 'Index should be 0');
component.get('actions').next();
assert.equal(component.get('index'), 1, 'index should be 1');
});
但它失败,错误为“this.incrementProperty不是函数”。调试时,测试中的“this”在next()函数中时,不是组件的上下文——它是一个对象,next()是其唯一属性
我想知道这是否是因为我在测试中调用了nextPlace操作。我知道我可以编写一个集成测试,单击触发此操作的按钮并比较一些UI以确保其更改,但当我试图测试的只是函数本身按预期执行时,这似乎非常复杂。如果它是一个传递给这个组件的动作(闭包动作),我知道我可以在集成测试中设置一个虚拟函数,将其传递给组件,并查看它如何响应。但是这个动作并不调用传递给它的动作
我意识到我正在测试的功能非常基本,但部分原因是为了理解如何在不调用外部(组件)操作的组件中测试操作。如果您没有表达不编写集成测试的动机,我只建议您编写集成测试。依我看,你的理由是正确的。我有3条建议可以引导您案例的单元测试 首先:不工作的原因是“
component.get('actions')。next
在没有任何上下文的情况下获取对next
函数的引用。因此此
在该调用中无效。要使其有效,只需将组件绑定到它,如下所示:
component.get('actions').next.bind(component)();
next(){
this.incrementProperty('index');
},
actions:{
next(){
this.next();
}
}
但是我不喜欢这样,因为它是从上下文中提取next
并再次绑定它。我们正在做bind
的事情,因为我们知道next
函数在其代码中引用了this
因此,我的第二个建议是“如何触发事件”。要触发事件,请查看以下代码:
component.send('next');
依我看,这样更好。我们不需要知道“下一步要做什么”。我们只是在触发一个事件
但这涉及到ember组件的生命周期。我们接受这种情况:有一个名为actions
的特定哈希,我们可以通过send
触发它(这完全可以)我们不需要处理操作
,而可以将做某事
与操作处理
分开。这样,您就可以定义另一个函数来执行所需操作,只需从您的操作处理程序调用它即可。(好的,在这种情况下,我们再次需要知道操作处理程序调用的函数是什么。但这对我来说似乎更清楚。)如下图所示:
component.get('actions').next.bind(component)();
next(){
this.incrementProperty('index');
},
actions:{
next(){
this.next();
}
}
您可以同时看到所有三个备选方案