如何在Ember.js中测试组件方法?

时间:2017-05-26 05:57:55

标签: javascript testing ember.js integration-testing ember-testing

我有一个方法和服务的组件,可以为某些组件运行函数。

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)或者我该如何重构这种方法呢?

1 个答案:

答案 0 :(得分:3)

我会尽力回答你的问题;在开始之前,请查看我为您准备的以下twiddle。我刚刚复制了你的组件和服务定义;但是还为组件添加了willDestroyElement,为服务添加了unregisterComponent以进行必要的清理以从服务中删除组件。请注意要完成的清理工作;如果你根本不考虑它,你可能会遇到大麻烦。关于你的问题;

1)您不得直接调用bar方法进行组件测试。你需要做的是渲染组件;检查一些断言;并调用服务的runBar方法,以便在集成测试中调用组件的bar方法。据我所知,这是您心目中的情景。请查看我在上面提供的旋转中的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)用于测试服务;你可以写一个单元测试,这就是我在旋转中所做的。注意;您不需要实际组件来注册该服务;所以我使用了stub组件(只是旋转中Ember.Object的虚拟实例)。其余的很容易遵循我相信。我只是调用服务的runBar方法并检查预期的断言。

3)现在这是一个难题;因为很难从你提供的代码片段中看到你制作这样一个设计的意图。尽管如此;我对重构的评论如下:请尽量避免将组件注册到其他构造(父组件,子组件,控制器,路由,服务等)。恕我直言,组件的内部函数应该只能由组件本身调用。组件的接口应该是由组件触发的事件(我指的是从外部提供的动作)和要从外部传递的属性。我并不声称在任何情况下都应避免您的设计;但只有在没有其他选择的情况下才必须谨慎使用。主要原因是;具有这种设计的代码的可追溯性应该成为一场噩梦。任何有权访问该服务的人都应该对组件(已注册到该服务)进行更新,而该组件对此一无所知。这是我真的不喜欢的事情。我的建议是依赖于定义良好的API,以便组件不会传递它并从不相关的地方对其进行更新。

这是一篇很长的帖子;我希望它有所帮助。