Сервис не внедрен в интеграционный тест компонента
У меня есть сервис 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
автоматически или через шаблон). Это может быть не идеальное решение, которое вы хотели бы иметь; но это достаточно хорошо, чтобы сохранить ваш код, как вы хотите, с гораздо меньшей суетой.