dimanche 25 juin 2017

Service not injected into component's integration test

I have a service Foo (e.g. app/services/foo.js):

import Ember from 'ember';

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

export default FooService;

which I initialize in app's initializers (e.g. app/initializers/foo.js), such as:

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

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

export {initialize}
export default FooInitializer;

And then I have a component (e.g. app/components/my-component.js), in which I use this service (I do not inject it manually here because it's already injected into every component in initializers):

import Ember from 'ember'

const MyComponent = Ember.Component.extend({

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

});

export default MyComponent;

I created integration test for this component:

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``);
  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");
});

When running this test, it throws an error:

TypeError: Cannot read property 'myMethod' of undefined

which means the service is not being injected, even thought I injected it in the test manually as a stub.

I read a couple of discussions, but none was really helpful until I bumped into this one which hinted me that Ember might not inject services into tests if they are initialized using initializers and not injected manually into the component that is being tested.

So I tried to inject the service manually into the component and the test worked. This is, however, only partial solution since it completely destroys the purpose of initializers if I have to inject services into my components (and there's a lot of them) manually just to make the tests work.

Have any of you experienced this and if so, is there something I'm doing wrong or is there a workaround to make this work without manually injecting my services into every component that I have? Maybe this will end up filing a bug in Ember, but I first wanted to try stackoverflow to see if there's another solution.




Aucun commentaire:

Enregistrer un commentaire