Mocking Integration Test Data with Ember CLI Mirage

You already know how to test your components but… how do you mock your complex data model?

In that guide we created a helper that returns a bunch of Ember.Objects. This approach is perfect to get up and running but falls short in many aspects. For example if you need to test relationships.

Enter the fantastic Ember CLI Mirage.

Setting it all up

$ ember install ember-cli-mirage

You should notice a file structure created at app/mirage! (Otherwise, try running ember generate ember-cli-mirage.)

Following the Wine Bar application in the previous guide, our first “backend” model will be called Wine and located at app/mirage/factories/wine.js. We create the file and make it look like this:

// app/mirage/factories/wine.js

import Mirage, {faker} from 'ember-cli-mirage';

export default Mirage.Factory.extend({

  name: faker.list.cycle('Zisola Sicilia',
    'Ribera del Duero',
    'Clos Fourtet St.-Emilion',
    'Blandy Bual Madeira',
    'Baer Ursa',
    'Tenet Syrah Columbia Valley',
    'Oddero Barolo',
    'Lavau Gigondas',
    'Duorum Douro',
    'Philippe Alliet Chinon',
    'Orin Swift Machete'),

  quantity: faker.list.random(23, 54, 12, 10, 4, 280)

});

The package faker ships with Mirage, we’ll use it to return names from a list and generate random quantities for our wine stock.

There are several options for our model attributes:

// app/mirage/factories/wine.js

import Mirage from 'ember-cli-mirage';

export default Mirage.Factory.extend({
  name: ...,
  quantity: ...,

  age: 10,
  recommended: true,

  inStock() {
    return this.quantity > 0;
  },

  cellar(i) {
    return `Cellar ${i}`;
  }

});

Mirage factories docs have further information.

Mocking the API

Naturally, we’ll need to setup endpoints for retrieving these fake models:

// app/mirage/config.js

export default function() {
  this.get('/wines');
  this.put('/wines/:id');
}

Ember CLI Mirage 0.1.x exposes a REST API and Ember Data should be aware. Let’s ensure we have the correct adapter and serializer:

# if needed

$ ember g adapter application
$ ember g serializer application

Double check:

Hooking up Mirage to our integration tests

First thing we’ll do is create a helper at tests/helpers/start-mirage.js to initialize Mirage:

// tests/helpers/start-mirage.js

import mirageInitializer from '../../initializers/ember-cli-mirage';

export default function startMirage(container) {
  mirageInitializer.initialize(container);
}

And invoke it in our test setup hook:

// tests/integration/components/wine-stock-test.js
// -- or wherever your integration test is located

import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import startMirage from '../../helpers/start-mirage';

moduleForComponent('wine-stock', 'Integration | Component | wine stock', {
  integration: true,
  setup() {
    startMirage(this.container);
  }
});

Perfect! Now we are ready to use Mirage in our tests:

// any test

test('it renders', function(assert) {
  assert.expect(5);

  const model = server.createList('wine', 12);

  this.set('model', model);
  this.render(hbs`{{wine-stock wines=model}}`);

  // assertions...

});

That should work!

In development mode, Mirage will display the response of the mock server in the console.

Above we called createList which returns plain objects – not Ember.Objects. If we want to access properties the Ember way in our tests, we can do:

const model = server.createList('wine', 12).map(wine => Ember.Object.create(wine));

Definitely take some time to read Mirage’s excellent documentation and test drive it! It’s a great mock server that will be worth your while.

It’s also a perfect companion for development work if your models are not so simple.

Enjoyed this article? Don't miss my next one!

Leave me your e-mail for content that will help you master Ember:

Do you want to master Ember fast?

Leave me your e-mail for helpful updates delivered straight to your inbox.

(A few e-mails per month. No BS. Unsubscribe anytime!)