BLOG

JavaScript Unit Testing - backbone.js

This is the first in a series of posts on unit testing in javascript. I get the opportunity to work on a variety of projects at several companies and have seen just as many different approaches to unit testing. I’d like to start sharing some techniques I’ve seen. Kicking things off with backbone.js.

It’s been two years since I posted Browser Unit Testing with Backbone, Mocha, Chai, and RequireJS and I still think that’s a good template for getting started if you’re starting a backbone application today. That talked about how to get the framework setup. Let’s talk now about what you could and should be testing.

I usually make sure my backbone applications have tests for:

  • Any logic put into the models or collections. One strategy for backbone applications is to make fat models that contain lots of business logic. If that’s the case for your application, you’ll want good unit tests around those models.
  • Basic view logic asserting that the core HTML you’re expecting to be rendered does so. Careful here that you only assert business logic and not design/styling.
  • Any custom logic you might have created such as helper methods.

Model / Collection Assertions

If you put a lot of logic into your models or collections, you’ll want to have unit tests that specifically call these objects and test just their functionality in isolation. As with everything else when unit testing, the key to this is making sure that your models/collections are coded in such a way that they don’t have hard dependencies on other parts of your application.

For example, try not to do things like this:

var Post = Backbone.Model.extend({
  urlRoot: '/api/posts',
  getCount: function() {
    // This assumes this model is linked to a collection
    // which means more setup in the unit tests
    var posts = this.collection;
    return posts.length;
  }
});

View Logic Assertions

The most important thing in doing View assertions is that all of your views need to scope everything locally. The easiest one to get wrong is calling jQuery directly, instead of the locally scoped version of jQuery that backbone provides. For example:

// ... view snippet ...
render: function() {
  var posts = this.collection.toJSON();
  var html = template(data);
  this.$('[data-bind="posts"]').html(html);
  return this;
}

Referring to this.$ instead of just $, means that jQuery will be scoped to the current view. This not only helps backbone render the correct thing if you re-use selectors, but also helps us unit test without having to render the HTML to our spec runner.

Sample Application

In the gist below, I’ve created the guts of a sample application that assumes we’re trying to render posts to a page and how that would be unit tested.

calendartwitterfeedenvelopelinkedinangellistgithub-altbitbucketheart