Testing in Ember.js, Part 3: mock data with ember-cli-mirage

When Last We Left Our Heroes…

The goal of automated testing is to find problems before your users do. Good tests do this by preventing bad code from being merged. A great continuous integration (CI) setup can catch problems in beta browsers and libraries in time to report them to their authors or fix your code before a release happens. By the end of this three part series you will have a great CI setup. Tests will automatically run against any browser you support and any future version of your dependencies.

In Part One, we covered using Sauce Labs and Travis CI to create your test matrix.

In Part Two, we covered testing our application against many versions of Ember.

In Part Three, we will write some acceptance tests and use the awesome ember-cli-mirage addon to provide controlled mock data to our tests and development environment.

Getting Set Up

Part Three picks up right where we left off with a working ember-cli project and build configuration. This is not a tutorial on Test Driven Development so we’re going to start out with a working example and then test it.

First setup our ember-data models:

[code language=”bash”]
$ cd testing-sandbox
$ ember g model fruit title:string color:belongsTo
$ cat app/models/fruit.js
import DS from ’ember-data’;
export default DS.Model.extend({
title: DS.attr(‘string’),
color: DS.belongsTo(‘color’, {async: true})
});

$ ember g model color title:string fruits:hasMany
$ cat app/models/color.js
import DS from ’ember-data’;

export default DS.Model.extend({
title: DS.attr(‘string’),
fruits: DS.hasMany(‘fruit’, {async: true})
});

[/code]

Then a simple route:

[code language=”bash”]
$ ember g route colors –path=’/colors’
[/code]

Modify app/routes/colors.js to get all the colors:

[code language=”javascript”]
import Ember from ’ember’;

export default Ember.Route.extend({
model(){
return this.store.find(‘color’);
}
});
[/code]

Setup a template to list the colors and their fruits app/templates/colors.hbs

[code language=”text”]
<ul>
{{#each model as |color|}}
<li>{{color.title}}
<ul>
{{#each color.fruits as |fruit|}}
<li>{{fruit.title}}</li>
{{/each}}
</ul>
</li>
{{/each}}
</ul>
[/code]

Setup ember-cli-mirage

Let’s install the ember-cli-mirage addon.

[code language=”bash”]
$ ember install ember-cli-mirage
[/code]

Now we need to configure our basic API routes. Mirage creates a basic configuration file for you at app/mirage/config.js. We just need to add a few lines for our new models:

[code language=”javascript”]
export default function() {
this.get(‘/colors’);
this.get(‘/colors/:id’);
this.get(‘/fruits’);
this.get(‘/fruits/:id’);
};
[/code]

For each of our models we need a factory so our tests can create new data. As ember-cli-mirage matures, generators for your factories will be added. For now, you have to make them on your own. We need one for fruit and one for color.

Create the file app/mirage/factories/fruit.js:

[code language=”javascript”]
import Mirage from ’ember-cli-mirage’;

export default Mirage.Factory.extend({
title: (i) => `fruit ${i}`,
color: null
});
[/code]

…and the file app/mirage/factories/color.js:

[code language=”javascript”]
import Mirage from ’ember-cli-mirage’;

export default Mirage.Factory.extend({
title: (i) => `color ${i}`,
fruits: []
});
[/code]

Wow. Thats was some serious setup; take heart that we’re done now and we can finally write a test.

Finally a test!

[code language=”bash”]
$ember g acceptance-test colors
[/code]

Add some fixture data and a test to your new file at tests/acceptance/colors-test.js:

[code language=”javascript”]
test(‘visiting /colors’, function(assert) {
//turn on logging so we can see what mirage is doing
server.logging = true;

//make our first color, its gets an id of one
server.create(‘color’, {
//fill this color with some fruits (they don’t exist yet, thats next)
fruits: [1,2,3,4,5]
});
//now lets create a bunch of fruits and link them to our color
server.createList(‘fruit’, 5, {
color: 1
});
//want another color? – just add it.
server.create(‘color’, {
fruits: [6,7]
});
server.createList(‘fruit’, 2, {
color: 2
});
visit(‘/colors’);

andThen(function() {
assert.equal(currentURL(), ‘/colors’);
//this is a stupid test, but hey its a tutorial, what did you expect?
assert.equal(find(‘li’).length, 9);
});
});
[/code]

Yup, I wrote that test for you. This isn’t a lesson on Test Driven Development. If you want that watch “Test Driven Development By Example”. The important part here is that we create fresh testing data with every test using server from ember-cli-mirage. You can be in complete control of what is passed to your application so you can check for any condition.

Final Thoughts

We’re just about out of time and we covered a lot. You still have some test writing to do and I wish there was an addon to do that for you. Until then you can take solace in the knowledge that your testing infrastructure is a foundation you can build your reputation on.

Until next time, Internet friends: If you liked it or hated it let me know @iam_jrjohnson.