如何在 Ember.js 中测试组件方法?
How to test component methods in Ember.js?
我有一个组件只有一个方法和服务,它可以 运行 对某些组件起作用。
export default Ember.Component.extend({
foo: false,
bar() {
this.set('foo', true);
},
someService: Ember.inject.service('some-service'),
didInsertElement: function () {
const someService = this.get('someService');
someService.registerComponent(this);
},
});
export default Ember.Service.extend({
components: [],
registerComponent: function (component) {
let components = this.get('components');
components.push(component);
},
runBar(index) {
let components = this.get('components');
components[index].bar();
}
});
1) 如何为 bar() 方法编写测试?
2) 以及如何为该服务编写测试?
3) 或者我该如何重构这种方法?
我会尽量按顺序回答你的问题;在开始之前,请查看以下 twiddle 我为您准备的内容。我刚刚复制了您的组件和服务定义;但还为组件添加了 willDestroyElement
并为服务添加了 unregisterComponent
以进行必要的清理以从服务中删除组件。请注意要进行的清理工作;如果你根本不考虑它,你会 运行 陷入大麻烦。关于您的问题;
1) 不得直接调用bar
方法进行组件测试。您需要做的是渲染组件;检查一些断言;并调用服务的 runBar
方法,以便在集成测试中调用组件的 bar
方法。据我了解,这是您脑海中的场景。请查看我上面提供的 twiddle 中的 my-component-test.js
文件。这个测试的关键部分可能是
Ember.run(()=>Ember.getOwner(this).lookup('service:some-service').runBar(0));
代码片段。 Ember.getOwner(this).lookup()
使您能够获取服务;请注意,您需要提供全名 (service:some-service
) 才能获取它。它处于 运行 循环中;因为它应该具有异步影响并且 Ember 会警告您。反正;我想测试本身很简单;因为组件所做的只是将 foo
属性 打印到屏幕上,并且在调用服务的 runBar
方法时 属性 从初始值设置为 true
false
.
2) 用于测试服务;你可以写一个单元测试,这就是我在胡闹中所做的。注意;您不需要实际组件来注册服务;所以我使用了存根组件(只是 Ember.Object
中的虚拟实例)。我相信其余的很容易理解。我只是调用服务的 runBar
方法并检查预期的断言。
3) 现在这是个难题;因为仅从您提供的代码片段中很难看出您进行此类设计的意图。尽管如此;我对重构的评论如下:请尽可能避免将组件注册到其他构造(父组件、子组件、控制器、路由、服务等)。恕我直言,组件的内部函数只能由组件本身调用。组件的接口应该是组件要触发的事件(我的意思是从外部提供的动作)和从外部传递的属性。我不主张在任何情况下都应避免您的设计;但只有在没有其他选择的情况下才必须小心使用。主要原因是;这样设计的代码的可追溯性应该会成为一场噩梦。任何有权访问该服务的人都应该更新它一无所知的组件(已注册到该服务)。这是我非常不喜欢的事情。我的建议是依赖定义良好的组件 API,而不是四处传递它并导致从不相关的地方对其进行更新。
这已经很久了post;希望对你有帮助。
我有一个组件只有一个方法和服务,它可以 运行 对某些组件起作用。
export default Ember.Component.extend({
foo: false,
bar() {
this.set('foo', true);
},
someService: Ember.inject.service('some-service'),
didInsertElement: function () {
const someService = this.get('someService');
someService.registerComponent(this);
},
});
export default Ember.Service.extend({
components: [],
registerComponent: function (component) {
let components = this.get('components');
components.push(component);
},
runBar(index) {
let components = this.get('components');
components[index].bar();
}
});
1) 如何为 bar() 方法编写测试?
2) 以及如何为该服务编写测试?
3) 或者我该如何重构这种方法?
我会尽量按顺序回答你的问题;在开始之前,请查看以下 twiddle 我为您准备的内容。我刚刚复制了您的组件和服务定义;但还为组件添加了 willDestroyElement
并为服务添加了 unregisterComponent
以进行必要的清理以从服务中删除组件。请注意要进行的清理工作;如果你根本不考虑它,你会 运行 陷入大麻烦。关于您的问题;
1) 不得直接调用bar
方法进行组件测试。您需要做的是渲染组件;检查一些断言;并调用服务的 runBar
方法,以便在集成测试中调用组件的 bar
方法。据我了解,这是您脑海中的场景。请查看我上面提供的 twiddle 中的 my-component-test.js
文件。这个测试的关键部分可能是
Ember.run(()=>Ember.getOwner(this).lookup('service:some-service').runBar(0));
代码片段。 Ember.getOwner(this).lookup()
使您能够获取服务;请注意,您需要提供全名 (service:some-service
) 才能获取它。它处于 运行 循环中;因为它应该具有异步影响并且 Ember 会警告您。反正;我想测试本身很简单;因为组件所做的只是将 foo
属性 打印到屏幕上,并且在调用服务的 runBar
方法时 属性 从初始值设置为 true
false
.
2) 用于测试服务;你可以写一个单元测试,这就是我在胡闹中所做的。注意;您不需要实际组件来注册服务;所以我使用了存根组件(只是 Ember.Object
中的虚拟实例)。我相信其余的很容易理解。我只是调用服务的 runBar
方法并检查预期的断言。
3) 现在这是个难题;因为仅从您提供的代码片段中很难看出您进行此类设计的意图。尽管如此;我对重构的评论如下:请尽可能避免将组件注册到其他构造(父组件、子组件、控制器、路由、服务等)。恕我直言,组件的内部函数只能由组件本身调用。组件的接口应该是组件要触发的事件(我的意思是从外部提供的动作)和从外部传递的属性。我不主张在任何情况下都应避免您的设计;但只有在没有其他选择的情况下才必须小心使用。主要原因是;这样设计的代码的可追溯性应该会成为一场噩梦。任何有权访问该服务的人都应该更新它一无所知的组件(已注册到该服务)。这是我非常不喜欢的事情。我的建议是依赖定义良好的组件 API,而不是四处传递它并导致从不相关的地方对其进行更新。
这已经很久了post;希望对你有帮助。