In this first article in a series on unit testing JavaScript web apps I’ll show Jasmine for testing an object inheriting from Backbone.Model. In particular we’ll review simulating service responses and exercising accessor functions.

Test App Repo

I wrote a sample app supporting this article by putting concepts into practice. If you want to get your hands on something and poke around feel free clone it from here:

Once you pull down that code running tests means opening this file in Chrome:

JasmineTestingBackBoneModel/tests/SpecRunner.html

Jasmine’s unit test reporting looks like:

When you have a chance read through SpecRunner.html looking for how it organizes <script> tags bringing in dependent JavaScript libraries, app-specific code, and Jasmine support. It’s straight-forward with a few rules to abide success will be yours.

Jasmine Resources

I won’t try training you on Jasmine to any extent. If you already know it then cool, but otherwise check out these docs for more domain-specific knowledge.

What’s Up With Mock Data

Pretending to have a service response is far quicker than hitting the real end-point. Jasmine lets us short-circuit a Model.fetch() by immediately returning an object imitating an evaluated JSON response.

Great, now that you’re convinced that mocking out the service response makes unit tests respond more quickly, I’ll also claim that testing the models doesn’t require testing the service or the transmission mechanisms.

Organize Tests As If Reading a Story

You’ll see the Jasmine unit tests are hierarchically organized into larger suites and specs blocked by subject, and those are broken into detailed expectations. Reading them in a cascading flow appears like revealing narrative.

A Coffee Model

has property getting functions that

should return the name

A Coffee Model

when it fetches

should be able to parse mocked service response

At this point you might be wondering “what’s up with the coffee thing?” This example test is written around the defining model for my site “Made Fresh Coffee” where people virtually mix tasty ingredients, or pull from a complete recipe list, creating a virtual coffee sent to their favorite people.

Code Reading

Let’s go through code snippets of the example project seeing how Jasmine helps us unit test application code, and why I decided to do things a certain way.

Reading “Should be able to create its application test objects”

This is my convention kicking off a unit test assuring the simplest things are done. Creating the thing that needs testing and resources supporting that.

In this case App.Model.Coffee is the model declared in the application’s global namespace. All of that code is brought into the test runner through various <script> tags written in SpecRunner.html.

MOCK_GET_DATA is an object defining what a coffee model definition looks like when calling to services. We can make these by looking at the “network” table in Chrome’s developer tools window while the app runs against a live service. Capture that output and write a mock data fixture.

Reading “…Should Return the Name”

Reading “Has Property Setter Functions That…”

Creates its own application model for the suite of expectations following. Why bring in a new model? Just in case. Clean-room testing feels like the right thing to do most of the time. Realize that it() blocks can easily affect the test object creating side-effects rippling through down-stream expectations. Use your own judgement on this technique.

Reading “…Should Set the New Ingredients”

This block calls the model’s set function with an intended value, and then expects to find the proper values stored in the Backbone attribute. Why not use the app object’s corresponding .getIngredients() function? A fair question and we could do. Perhaps its just a matter of taste, but in this case I like the idea of testing more deeply by looking into the implementation details.

Reading “When It Fetches”

Now we’re getting to a fun test. Jasmine “spies” are used switching away context from a JavaScript function for one of Jasmine’s own. Spies observe caller information and return with its own results (unit test) or passing through (integration test).

My example code shows one way of putting spies into action by short-circuiting Backbone.Model.fetch() calling to $.ajax() by returning MOCK_GET_DATA.

Jasmine beforeEach() and afterEach() statements are used in another attempt at being professional and scientific creating clean well-known test objects before each it() block. Jasmine will call beforeEach before each it() block and afterReach after each it() block. No surprises there.

Reading “should be able to parse mocked service response”

Granted this seems a bit procedural, but it confirms an assumption that the proper data is available by checking each Backbone.Model attribute expected from a service response.

it('should be able to parse mocked service response', function() {
expect(_.isEmpty(coffee.attributes)).toEqual(false);
expect(coffee.get('author')).toEqual('Ken Tabor');
expect(coffee.get('ingredients')).toEqual([18, 15, 1, 1, 1]);
expect(coffee.get('message')).toEqual('Heya everyone, we have a crazy big deadline coming up but I know we can do it. Let\'s enjoy a coffee and finish strong!');
expect(coffee.get('name')).toEqual('Basic Drip');
expect(coffee.get('readUrl')).toEqual('http://www.madefreshcoffee.com/read.php?sku=bd86292a-241a-11e2-b97c-12313d04a24a');
});

Your model might have a more complicated .parse() function perhaps synthesizing new attributes having unpacked and interpreted the service response. Given that case you can see where this is an even more interesting test.

More Tests Remain for Reading

Of course there are more tests in this sample spec. Please read them when you pull down the example code from my GitHub repo. The one checking $.ajax parameters is unique.

A Few of My Favorite Favorite Matchers

Do I actually have favorite matchers? In fact I do. Jasmine matchers compare a test object result with an expected value. I keep my toolbox lightweight assuring that what I use I use often and well.

.toEqual(‘booga booga’);

.toBeDefined();

.toBeUndefined();

Consider using and mastering just a few matchers to start. Dip into the Jasmine docs from time to time drawing up a few more features calling you. Incorporate them into your project when you’re feeling confident.

Realize that other Jasmine matcher libraries exist and you ought to explore those to use straight-up or serve as a jumping-off point for building your own. I particularly admire jasmine-jquery because it exposes semantic tests for DOM elements. Awesome stuff for my upcoming article on unit testing Backbone.View objects.

Further R&D Left to the Reader

My article is only the start of proper JavaScript unit testing. You’ll want to discover some of the following techniques for professional engineering:

Take Advantage of Jasmine

Have a think on all of this. Unit testing using Jasmine is a wonderful way to power up the professional quality of your web app. Dynamic languages like JavaScript are nimble and flexible for us, but they don’t help craft fantastically stable application architecture.

Unit testing with Jasmine can build up your confidence level making programming life easier. Have a coffee and watch your application grow in a reliable manner.