javascript - 对 Ember Controller 中的异步函数进行单元测试

标签 javascript unit-testing asynchronous ember.js qunit

我遇到了一个非常奇怪的问题:我正在尝试进行单元测试以在我的应用程序上实现 100% 的测试覆盖率。 当然,我为我的 Controller 编写了一些测试,但似乎无法使用 ember-cli 测试 Ember (2.4.0) 中的任何异步内容。

  1. 我在 Controller 中有一个函数可以执行此操作:

    readObject() {
       this.store.findRecord('myModel',1).then(function(obj) {
          this.set('property1',obj.get('property2');
       }.bind(this));
    }
    
  2. 我正在编写一个应该涵盖此功能的测试。

    test('action readObject', function (assert) {
       const cont = this.subject();
       cont.readObject();
       assert.equal(cont.get('property1'), 'someValue);
    });
    
  3. 显然,这个断言不起作用,因为 readObject() 是异步调用,但这不是问题的根源。问题是,然后 this.store.findRecord 中的回调正在执行 - 我的 Controller 已经被破坏!所以我得到了“在被破坏的对象上调用集”错误。

换句话说 - 即使我将我的函数包装在一个 promise 中并重新格式化这两个函数,如下所示:

readObject() {
   return new Promise(function(resolve) {
       this.store.findRecord('myModel',1).then(function(obj) {
          this.set('property1',obj.get('property2');
          resolve();
       }.bind(this));
   }.bind(this));
}

test('action readObject', function (assert) {
  const cont = this.subject();
  cont.readObject().then(function() {
      assert.equal(cont.get('property1'), 'someValue);
  });
});

它不起作用,因为执行 readObject() 后我的 Controller 立即被销毁,而不等待任何回调。 因此,它可以是任何异步调用,而不是 store.findRecord - 例如,它可以是 Ember.run.later。

有人遇到同样的问题吗?我读过很多文章,我不敢相信拥有如此大社区的 Ember 竟然没有提供异步单元测试的方法。

如果有人有任何线索 - 请给我提示,因为我有点迷失在这里。目前我有两个想法:

  1. 我把 Controller 弄错了,Ember 不认为其中有任何异步操作。但即使我将异步调用移至服务 - 我在为它们编写单元测试时遇到了同样的问题。

  2. 我必须将我的功能分解为

    readObject() {
      this.store.findRecord('myModel',1).then(this.actualReadObject.bind(this));
    }
    
    actualReadObject(obj) {
       this.set('property1',obj.get('property2');
    }
    

至少要让回调主体覆盖测试,但这意味着我永远不会在我的应用程序中获得 100% 的测试覆盖率。

提前感谢您提供任何线索。 :)

最佳答案

我遇到了类似的问题,正在查看 QUnit API - async我解决了。尝试以下操作:

// ... in your controller ...
readObject() {
   return this.store.findRecord('myModel',1).then(function(obj) {
      this.set('property1', obj.get('property2');
   }.bind(this));
}

// ... in your tests, either with assert.async: ...
const done = assert.async(); // asynchronous test due to promises usage
Ember.run(function(){
    subject.readObject().then(function(){
      // once you reach this point you are sure your promise has been resolved
      done();
   });
});


// or without assert.async
let promise;
Ember.run(function(){
    promise = subject.readObject();
});
return promise; 

在单元测试的情况下,我还模拟其他依赖项,例如:store。

this.subject({
   property1: null, 
   store: {
      findRecord(modelName, id){
         assert.equal(modelName, "myModel1");
         assert.equal(id, 1);
         return new Ember.RSVP.Promise(function(resolve){
            resolve(Ember.Object.create({ property2: "a simple or complex mock" }));
        })
      }
   }
});

我不确定第二种情况(没有 assert.async 的情况)。我认为它也会起作用,因为测试套件返回一个 promise 。这会被等待 promise 的 QUnit 识别。

关于javascript - 对 Ember Controller 中的异步函数进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36574693/

相关文章:

javascript - jQuery 简单对话框事件

javascript - 如何直接在Sequelize中更改预加载的结果

unit-testing - 如何在 CI 管道中对使用不属于 git 远程的模型文件的函数进行单元测试?

Android - 对调用 JNI 函数的类进行单元测试?

python-3.x - 无法连接到docker容器内的postgres数据库

java - Spring 异步未捕获异常处理程序

javascript - JQuery UI 可拖动多个恢复选项

javascript - 仅对最后加载的项目进行动画处理(ajax loadmore)

unit-testing - PyCharm unittest error : Provide a qualified name of function, 类或模块

.net - 如何在 .net 内存转储中列出正在运行的任务