我对Ember有点新,并试图测试一个寻呼机组件。简化组件如下所示:
export default Ember.Component.extend({
index: 0,
actions: {
next() {
this.incrementProperty('index');
}
}
});
我试图测试next()动作是否确实按预期增加了索引属性。我写了一个像这样的单元测试:
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不是函数"。调试,"这个"在测试中,当在next()函数内部时,不是组件的上下文 - 它是一个以next()作为唯一属性的对象。
我想知道这是不是因为我在测试中调用了nextPlace动作。我知道我可以编写一个集成测试,点击触发此操作的按钮并比较一些UI以确保它发生了变化,但是当我尝试测试的所有功能本身都按预期执行时,这似乎非常复杂。如果它是一个传递给这个组件的动作(关闭动作),我知道我可以在集成测试中设置一个虚函数,将它传递给组件,看看它是如何响应的。但是这个动作并没有调用传递给它的动作。
我意识到我测试的功能非常基本,但部分原因是要了解如何测试不会调用外部(到组件)操作的组件中的操作。
答案 0 :(得分:2)
如果您没有表达不编写集成测试的动机,我建议您编写集成测试。 IMO,你的理由是有效的。我提出了3个启动单元测试的建议。
首先:不工作的原因是“component.get('actions').next
在没有任何上下文的情况下获得对next
函数的引用。因此this
在该调用中无效。它有效,只需将组件绑定到它,如下所示:
component.get('actions').next.bind(component)();
但我不喜欢这个,因为它从它的上下文中提取next
并再次绑定它。我们正在执行此bind
项操作,因为我们知道next
函数在其代码中引用了this
。
所以我的第二个建议就是“触发事件如何”。要触发它,请查看以下代码:
component.send('next');
IMO,这是更好的。我们不需要知道“接下来做什么”。我们只是在触发一个事件。
但这涉及到ember组件的生命周期。我们接受这种情况:有一个名为actions
的特定哈希,我们可以通过send
触发它。 (这完全没问题。)我们可以从actions
分离doing something
,而不是处理action handling
。因此,您可以定义另一个函数来执行您需要的操作,并从操作处理程序中简单地调用它。 (好吧,在这种情况下,我们再次需要知道动作处理程序调用了什么函数。但这对我来说似乎更清楚。)如下所示:
next(){
this.incrementProperty('index');
},
actions:{
next(){
this.next();
}
}
您可以在this twiddle找到所有三种选择。