服务未注入组件的集成测试

时间:2017-06-26 06:19:30

标签: ember.js qunit ember-qunit

我有服务Foo(例如app/services/foo.js):

import Ember from 'ember';

const FooService = Ember.Service.extend({
  myMethod() { ... }
});

export default FooService;

我在app的初始值设定项中初始化(例如app/initializers/foo.js),例如:

const initialize = function initialize(app) {
  app.inject('component', 'foo', 'service:foo');
}

const FooInitializer = {
  name: 'foo',
  initialize: initialize
}

export {initialize}
export default FooInitializer;

然后我有一个组件(例如app/components/my-component.js),我使用这个服务(我不在这里手动注入它,因为它已经注入初始化器中的每个组件):

import Ember from 'ember'

const MyComponent = Ember.Component.extend({

  actions:
    doSomething() { this.get('foo').myMethod(); }

});

export default MyComponent;

我为这个组件创建了集成测试:

import { test, moduleForComponent } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import sinon from 'sinon';

const fooStub = Ember.Service.extend({
  myMethod() {
    return true;
  }
});

moduleForComponent('my-component', 'Integration | Component | my-component', {
  integration: true,

  beforeEach() {
    this.register('service:foo', fooStub);
    // Calling inject puts the service instance in the context of the test,
    // making it accessible as "foo" within each test
    this.inject.service('foo', { as: 'foo' });
  }
});

test('it does something', function (assert) {
  this.render(hbs`{{my-component}}`);
  const spy = sinon.spy(this.get('foo'), 'myMethod');

  const $someElement = this.$().find('.some-element-within-my-component');
  // This element triggers `doSomething` action inside the component
  $someElement.click();

  assert.ok(spy.calledOnce, "myMethod was called within foo service");
});

运行此测试时,会抛出错误:

TypeError: Cannot read property 'myMethod' of undefined

这意味着服务没有被注入,甚至认为我在测试中将其作为存根手动注入。

我读了几个讨论,但没有一个真正有用,直到我遇到this one,这暗示我如果使用初始化程序初始化Ember而不是手动注入到组件中,则Ember可能不会将服务注入测试正在接受测试。

所以我尝试将服务手动注入组件并且测试工作正常。然而,这只是部分解决方案,因为如果我必须手动将服务注入我的组件(并且其中很多都是为了使测试工作),它完全破坏了初始化器的目的。

你们中是否有人经历过这种情况,如果有的话,是否有什么我做错了,或者有没有办法解决这个问题而无需手动将我的服务注入到我拥有的每个组件中?也许这最终会在Ember中提交一个错误,但我首先想尝试使用stackoverflow来查看是否还有其他解决方案。

1 个答案:

答案 0 :(得分:1)

AFAIK,初始值设定项和实例初始化程序仅在acceptance-testing中运行。因此,在初始化程序内进行的任何注入都必须手动处理integration-testing。然而;恕我直言,这并不意味着您必须手动更改整个设计并将服务注入组件,以便测试通过。为什么不在渲染组件时将您创建的存根服务传递给组件?我的意思是:

this.render(hbs`{{my-component foo=foo}}`);

这只是将存根服务传递给组件。最后,您想要的是一种从外部将服务传递给组件的方法(通过初始化程序,它不会自动在integration-testing中运行,或通过模板运行)。这可能不是您想要的理想解决方案;但它足以让您按照自己的意愿保持代码,而不用大惊小怪。