Действия модульного тестирования в контроллере ember, которые возвращают обещания

У меня есть контроллер, который выполняет асинхронную операцию, которую я хотел бы проверить:

/*globals Ember, momnent*/
import { raw as icAjaxRaw } from 'ic-ajax';

//...

    actions: {
        foo: function() {
            var req = icAjaxRaw({
                type: 'POST',
                url: ApiUtils.apiUrl+'/dofoo',
                processData: false,
            });

            return req.then(
                function resolve(result) {
                    console.log(result.response);
                    this.set('fooLastDoneAt', moment());
                }.bind(this)
            );
        },

... и в тестах:

test('actions.foo', function() {
    expect(2);
    var ctrl = this.subject();
    var model = {
        fooLastDoneAt: moment().add(-10, 'days'),
    };
    ctrl.set('model', model);
    ok(ctrl.get('fooLastDoneAt').isBefore(moment().add(-1, 'days')), true, 'initial');
    ctrl.send('foo');
    ok(ctrl.get('fooLastDoneAt').isBefore(moment().add(-1, 'days')), false, 'updated date');
});

Однако это неизбежно приводит к возникновению ошибки в другом, не связанном тестовом примере:

"Uncaught Error: Assertion Failed: calling set on destroyed object"[

что должно происходить, потому что this.set('fooLastDoneAt', moment()); выполняется после того, как этот тестовый пример завершен, и тестовый исполнитель сделал teardown для этого модуля и перешел к следующему; пока действие еще выполняется.

Могу ли я дождаться асинхронного завершения действия, прежде чем перейти к следующему шагу модульного теста?


@ kingpin2k предлагает это решение, в котором вы передаете обещанный отложенный объект в действие. Тем не менее, в моем приложении само приложение никогда бы этого не сделало, и это кажется фундаментальной проблемой, если мне нужно изменить исходный код приложения, чтобы он мог быть протестирован - особенно потому, что он добавляет дополнительную сложность.

Существуют ли другие способы заставить выполнение теста ждать завершения действия?

1 ответ

Я бы пошел на QUnitstart()stop() функции.

Вот пример использования взятый из документации QUnit:

QUnit.test( "a test", function( assert ) {
  QUnit.stop();
  asyncOp();
  setTimeout(function() {
    assert.equals( asyncOp.result, "someExpectedValue" );
    QUnit.start();
  }, 150 );
});

Также библиотека ember-qunit покрывает это then,

Вот пример для ember-qunit

test('actions.foo', function() {
    expect(2);
    var ctrl = this.subject();
    var model = {
        fooLastDoneAt: moment().add(-10, 'days'),
    };
    ctrl.set('model', model);
    ok(ctrl.get('fooLastDoneAt').isBefore(moment().add(-1, 'days')), true, 'initial');
    ctrl.send('foo').then(function(){
      ok(ctrl.get('fooLastDoneAt').isBefore(moment().add(-1, 'days')), false, 'updated date');
    });
});

Я не тестировал код, поэтому надеюсь, что он решит вашу проблему

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