mardi 12 avril 2016

Unit testing async functions in Ember controllers

I've hit a very weird problem: I'm trying to make unit tests to achieve 100% testing coverage on my application. And of course I wrote some tests for my controllers but it seems like there is no way to test anything async in Ember (2.4.0) using ember-cli.

  1. I have a function in controller that does this:

    readObject() {
       this.store.findRecord('myModel',1).then(function(obj) {
          this.set('property1',obj.get('property2');
       }.bind(this));
    }
    
    
  2. I'm writing a test that should cover this function.

    test('action readObject', function (assert) {
       const cont = this.subject();
       cont.readObject();
       assert.equal(cont.get('property1'), 'someValue);
    });
    
    
  3. Obivously, this assert wouldn't work because readObject() is async call but this isn't the root of the problem. The problem is that then a callback in this.store.findRecord is being executed - my controller is already destroyed! So I get "calling set on destroyed object" error there.

In other words - even if I wrap my function in a promise and reformat both functions like this:

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));
}

and

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

It wouldn't work, because after executing readObject() my controllers become immediately destroyed, not waiting for any callbacks. So, it could be any async call instead of store.findRecord - it could be Ember.run.later, for example.

Does anybody had the same issue? I've read a lot of articles I can't believe that Ember with such a big community doesn't provide a way to make async unit tests.

If anyone has any clues - please give me a hint, cause I'm kinda lost here. At the moment I have two thoughts:

  1. I'm making controllers wrong, Ember doesn't suppose any async operations inside of it. But even if I move async calls to services - I hit the same problem with writing unit tests for them.

  2. I have to decompose my functions to

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

to have at least callbacks body covered with tests, but this means I never get 100% testing coverage in my app.

Thank you in advance for any clues. :)

Aucun commentaire:

Enregistrer un commentaire