简体   繁体   中英

How do we unit test a Model Mixin with ember-cli

I have few Ember.Mixin in my app that contains DS.attr() and / or DS.belongsTo() . I was wondering how should I unit test them ?

By default, ember-cli generate this test

test('it works', function(assert) {
  var MyModelObject = Ember.Object.extend(MyModelMixin);
  var subject = MyModelObject.create();
  assert.ok(subject);
});

But when I tried to interact with an DS.attr() I got the following error:

TypeError: Cannot read property '_attributes' of undefined
  at hasValue (http://localhost:4200/assets/vendor.js:90650:25)
  at Class.get (http://localhost:4200/assets/vendor.js:90730:13)
  at Descriptor.ComputedPropertyPrototype.get (http://localhost:4200/assets/vendor.js:29706:28)
  at Object.get (http://localhost:4200/assets/vendor.js:35358:19)
  at Class.get (http://localhost:4200/assets/vendor.js:49734:38)
  at Object.<anonymous> (http://localhost:4200/assets/tests.js:20126:25)
  at runTest (http://localhost:4200/assets/test-support.js:2779:28)
  at Object.run (http://localhost:4200/assets/test-support.js:2764:4)
  at http://localhost:4200/assets/test-support.js:2906:11
  at process (http://localhost:4200/assets/test-support.js:2565:24)

Which make senses. What is the best way to do it ? Should I create a DS.Model within the test and then apply the mixin on it ?

Thanks !

Unit testing a model mixin like this is a little tricky since it needs access to the store in order to create the model. Usually, the store is not available in mixin tests because there isn't even a container. Additionally, since we just want to test the mixin, we don't want to require a real model, so we can create and register a phony host model just for the tests. Here's how I did this.

First, pull in 'ember-data' and use the helpers from 'ember-qunit' instead of the stock helpers from 'qunit'. Replace this:

import { module, test } from 'qunit';

With this:

import { moduleFor, test } from 'ember-qunit';
import DS from 'ember-data';

Then, you update your module declaration like this:

moduleFor('mixin:my-model-mixin', 'Unit | Mixin | my model mixin', {
  // Everything in this object is available via `this` for every test.
  subject() {
    // The scope here is the module, so we have access to the registration stuff.
    // Define and register our phony host model.
    let MyModelMixinObject = DS.Model.extend(MyModelMixin);
    this.register('model:my-model-mixin-object', MyModelMixinObject);

    // Once our model is registered, we create it via the store in the
    // usual way and return it. Since createRecord is async, we need
    // an Ember.run.
    return Ember.run(() => {
      let store = Ember.getOwner(this).lookup('service:store');
      return store.createRecord('my-model-mixin-object', {});
    });
  }
});

Once you have this setup in place, you can then use this.subject() in individual tests to get an object for testing.

test('it exists', function(assert) {
  var subject = this.subject();
  assert.ok(subject);
});

At this point, it's just a standard unit test. You may need to wrap async or computed code in an Ember.run block:

test('it doubles the value', function(assert) {
  assert.expect(1);
  var subject = this.subject();
  Ember.run(() => {
    subject.set('someValue', 20);
    assert.equal(subject.get('twiceSomeValue'), 40);
  });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM