New Ember Application
We’ll start by creating a new Ember.js application. We’ll do this using Ember-CLI, the preferred way to start a new Ember application (per the Emberjs.com website, Figure 01)
To get started with Ember-CLI, you’ll need Node.js and NPM installed, it’s as simple as going to the Node website and clicking the big Install button on their homepage. Easy-peasy. Then it’s simply two commands:
Then change into the
contacts directory. Open that folder in an editor of your choice.
Finally, run the command
ember serve to have your app served up on port
4200. Navigate to http://127.0.0.1:4200, and you should see a simple “Welcome to Ember.js” message.
Running Your Tests
You can either navigate to http://127.0.0.1:4200/tests to see your tests, or you can run the
ember test command. If you want, you can also run a server that will execute your tests, that command is
ember test --serve.
contact model. We can generate the model and a unit test by using Ember-CLI’s awesome generators:
app/models) and a unit test (under
tests/unit/models/contact-test.js). Jump into the test file (
tests/unit/models/contact-test.js) and we’ll start by test driving a computed property on our
contact. We’re going to want a
fullName property on our
contact model. Let’s write a test to get started, ensuring that
fullName computes properly. We also want to make sure that it updates if we change the
lastName. Put this at the end of the
contact-test.js file. The test file already has one simple test in it, but the important part of the test is the
moduleForModel call. This is what allows us to test Ember Data models easily.
moduleForModel block in place, we can now write our tests. Be sure to also
import Ember from 'ember'; since we’ll be using
Ember.run in our tests.
moduleForModel takes the name of the model, a description, and a object of requirements.
There are 3 assertions in this test. You could break these up into 3 separate tests if you want, but since these are all related, I put them in one test. Most of this should be readable, but the
Ember.run calls might be confusing here. The reasoning for this is that our Ember tests are asynchronous. If we don’t wrap the
contact.set calls, we’ll get an error. When the app is in testing mode, automatic invocation of
Ember.run is disabled. Because of this, anytime we are creating or changing a model with bound or observed properties, we need to wrap them in
Ember.run. Meaning let the run loop complete before working against that property.
The first assertion checks to make sure that
fullName works, given our subject. The second, makes sure that the
firstName triggers a change for the
fullName. The final assertion does the same as the second, but for the
lastName. The code to make this test pass is as follows:
Let’s now work on a route. We’re going to want to list all the contacts on a route called
contacts. Turning to Ember-CLI’s generators, we can generate a route using the code:
ember g route contacts. This will create three files for us:
Since we’re using TDD, hop into the
tests/unit/routes/contacts-test.js file. The initial file contains
imports and the key part of testing routes,
moduleFor takes the name of the module, a description, and a object of requirements. I have added a description of “Contacts Route” to make our tests a little bit friendlier. We can now write a test for our route. We’re using Ember-Data so I know that our route is going to be using the Ember-Data
store. Since we aren’t testing the
store, we’ll mock the object in the test. Jump into
tests/unit/routes/contacts-test.js as we’ll put our tests there
find method returns a promise, so we’ll emulate that behavior in our mock
store. From there we can check the
_result of the model (remember, it’s a promise) and do a
deepEqual assertion to make sure it returns the list we expect.
Finally, here’s the code to make our test pass (in
Continuing with our testing, let’s see how we’d test a controller. We’ll use Ember CLI to generate our
contacts controller, using the command:
ember g controller contacts. This generates two files for us.
You know the drill by now, we’ll get started in the test file
tests/unit/controllers/contacts-test.js. We want to test that our controller is an
To start testing a controller, we need to use
Now, let’s write our test. We’ll simply test if there is a method
addObject, which only exists on the
And the simple code to make it pass…
Since we’re testing controllers, let’s look how we’d test an action. We need to create an action to set a flag of whether or not all of the contacts are selected. We’ll put a property on the controller called
selectAll and we’ll create an action called
We’ll tell QUnit that we
expect three assertions. This is a way to make sure more or less things sneak into your tests. It’s not required, but I figured I show you some additional commands you can use. Then we make sure the default value is
false and once we call
toggleSelectAll, we check to ensure the value is
true. We call the action one more time to make sure it actually toggles the value. Now for the controller code…
Through this post, you learned how to unit test a model, the router, and a controller. In my next post, I’ll show you how to do integration and acceptance testing, where we check the full stack instead of pieces in isolation. Both testing approaches are important to having quality code. I encourage you to check out the official testing documentation as there are more examples to help you.