Сервис не внедрен в интеграционный тест компонента

У меня есть сервис Foo (например app/services/foo.js):

import Ember from 'ember';

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

export default FooService;

который я инициализирую в инициализаторах приложения (например, 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

что означает, что сервис не внедряется, даже если я ввел его в тест вручную как заглушку.

Я прочитал пару дискуссий, но ни одна из них не была действительно полезной, пока я не наткнулся на эту, которая подсказала мне, что Ember может не внедрять сервисы в тесты, если они инициализируются с использованием инициализаторов и не вводятся вручную в тестируемый компонент.

Поэтому я попытался внедрить службу вручную в компонент, и тест сработал. Это, однако, только частичное решение, поскольку оно полностью разрушает цель инициализаторов, если мне нужно вручную внедрить службы в мои компоненты (а их много), чтобы тесты работали.

Кто-нибудь из вас испытывал это, и если да, то что-то я делаю не так или есть обходной путь, чтобы сделать эту работу без ручного внедрения моих сервисов в каждый компонент, который у меня есть? Возможно, это приведет к ошибке в Ember, но сначала я хотел попробовать stackru, чтобы посмотреть, есть ли другое решение.

1 ответ

Решение

AFAIK, инициализаторы и инициализаторы экземпляров работают только в acceptance-testing, Следовательно, любая инъекция, сделанная внутри инициализаторов, должна быть обработана вручную для integration-testing, Тем не мение; ИМХО, это не означает, что вы должны изменить весь свой дизайн и добавить сервис к компоненту вручную, чтобы пройти тест. Почему бы просто не передать созданную вами заглушку компоненту во время рендеринга компонента? Я имею в виду следующее:

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

Это просто передает сервис-заглушку компоненту. В конце концов, вам нужен способ передать сервис компоненту извне (либо через инициализатор, который не работает в integration-testing автоматически или через шаблон). Это может быть не идеальное решение, которое вы хотели бы иметь; но это достаточно хорошо, чтобы сохранить ваш код, как вы хотите, с гораздо меньшей суетой.

Другие вопросы по тегам