Модульное тестирование EmberJS 2.13: завершение синхронного кода в цикле выполнения?
Это повторяется несколько раз в текущей документации Ember, поэтому я чувствую, что, должно быть, что-то упустил. Давайте возьмем самый простой пример, который я нашел.
Почему вызов levelUp считается асинхронным, чтобы гарантировать его включение в цикл выполнения?
incrementProperty является синхронным, и, насколько я могу судить, так установлен (но я могу ошибаться здесь)
player.js
import DS from 'ember-data';
export default DS.Model.extend({
level: DS.attr('number', { defaultValue: 0 }),
levelName: DS.attr('string', { defaultValue: 'Noob' }),
levelUp() {
let newLevel = this.incrementProperty('level');
if (newLevel === 5) {
this.set('levelName', 'Professional');
}
}
});
игрок-test.js
import { moduleForModel, test } from 'ember-qunit';
import Ember from 'ember';
moduleForModel('player', 'Unit | Model | player', {
// Specify the other units that are required for this test.
needs: []
});
test('should increment level when told to', function(assert) {
// this.subject aliases the createRecord method on the model
const player = this.subject({ level: 4 });
// wrap asynchronous call in run loop
Ember.run(() => player.levelUp());
assert.equal(player.get('level'), 5, 'level gets incremented');
assert.equal(player.get('levelName'), 'Professional', 'new level is called professional');
});
2 ответа
Прежде всего, вы абсолютно правы. Это не очень хорошо описано нигде в руководствах.
В режиме тестирования автозапуск отключен. Вы можете прочитать далее в руководствах по этому поводу.
Но изменение значения в модели запускает цикл выполнения. Вы можете видеть это на этом повороте. Результат:
Assertion Failed: вы включили режим тестирования, который отключил автозапуск цикла выполнения. Вам нужно будет обернуть любой код с асинхронными побочными эффектами в прогоне
(Кстати, оба set
а также incrementProperty
запустите этот цикл выполнения, как вы думаете.)
Тогда вот источник цикла выполнения:
DS.attr
возвращает вычисляемое свойство с помощью set.set
Функция запускает событие.- В конце запускается цикл выполнения.
@ykaragol абсолютно прав в своем объяснении в своем правильном ответе, и мне нечего добавить, почему вам нужно заключить код в цикл выполнения; потому что исходный код есть и emberRun.schedule
вызывается, что требует выполнения цикла.
Я хотел бы объяснить немного больше об ошибке подтверждения, которую вы получаете: "Вы включили режим тестирования, который отключил автозапуск цикла выполнения. Вам нужно будет обернуть любой код асинхронными побочными эффектами во время выполнения". Это не означает, что асинхронная операция (в том смысле, что сделан вызов ajax или запущен таймер) имеет место. Мы в основном не знают, но; Ember.js использует Ember.run
циклы и различные очереди выполнения, такие как sync
, actions
, render
, afterRender
и т. д., чтобы запланировать эффекты наших кодов, чтобы оптимизировать рендеринг нашего приложения. Даже если код this.set('levelName', 'Professional');
кажется довольно синхронным; Ember помещает его в цикл выполнения, так что вычисляемое вычисление свойства или другие обновления буферизируются вместе для предотвращения многократного рендеринга (а значит, и снижения производительности) шаблонов.
Я только хотел, чтобы было лучшее объяснение о циклах выполнения, очередях выполнения или о том, как и почему использовать циклы выполнения в тестах, но это не так:(