【问题标题】:Unit testing actions in ember controller that return promisesember 控制器中返回承诺的单元测试操作
【发布时间】:2014-07-16 04:44:24
【问题描述】:

我有一个执行异步操作的控制器,我想对其进行测试:

/*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 建议this solution, 您将承诺延迟对象传递到操作中。 但是,在我的应用程序中,应用程序本身永远不会这样做, 如果我需要修改我的应用程序源,这似乎是一个基本问题 只是为了它可以被测试- 特别是因为它增加了复杂性。

还有其他方法可以让测试执行等待操作完成吗?

【问题讨论】:

    标签: javascript unit-testing ember.js ember-qunit ic-ajax


    【解决方案1】:

    我会选择 QUnit start() 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');
        });
    });
    

    我没有测试代码所以我希望它能解决你的问题

    【讨论】:

    • @saygun 感谢您回答这个问题,而我的previous one ... 对上一个问题没有完全回应,因为我被困在这个问题上!
    • @saygun 谢谢你的回答。像您建议的那样重新使用 QUnit 原语,适用于我的 previous question,因为属性获取和函数调用返回它们的承诺。
    • ctrl.send('foo').then(/* ... */) 确实 not 工作,因为通过 .send() 调用的控制器操作的返回值实际上并没有返回。正如@kingpin2k 提到的in his answer,“send 和 sendAction 是一条路”,因此我被困在了这条路上。这个问题的解决方案还是让我回避!
    猜你喜欢
    • 2014-01-15
    • 2016-03-27
    • 1970-01-01
    • 2014-11-26
    • 2015-03-15
    • 2016-07-25
    • 2016-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多