GitHub LinkedIn RSS
Sunday, July 20, 2014

Jasmine and Node.js


Following our last article about using Jasmine and Karma together, let's look how we streamline the testing of our server side code written in Node.js. To do this, we'll need to install jasmine-node package.
npm install -g jasmine-node
If you're not familiar with the tool, please read the JavaScript Developer Toolkit before proceeding any further. The installed version will only support Jasmine 1.3 version. In order to add the 2.0 support, you should install the branched version.
npm install -g jasmine-node@2.0.0-beta4
Again as in previous article we'll be using the specs from our previous Jasmine article and the source code can be found in GitHub. After installing the correct version, we'll have to make our Player and Song classes as CommonJS modules. If you don't know how, please read the article about Modular Design Patterns in JavaScript. And of course requiring them in our specs:
...
module.exports = Song;
...
module.exports = Player;
describe("Player", function() {
  var Player = require('../src/Player.js');
  var Song = require('../src/Song.js');
  ...
Everything is ready - let's run the spec. We do this by pointing the path of the spec
jasmine-node spec/
Andddd bummer - we receive an error:
Exception loading helper: c:\GitHub\jsdeepdive-jasmine-and-nodejs\spec\SpecHelper.js
[ReferenceError: beforeEach is not defined]
This happens because customer helpers are not supported :(
Removed Support for Custom Helpers (have to be inside a beforeEach, this is a jasmine change, check out their docs on how to write one)
So let's put our helper inside the spec.
  beforeEach(function() {
    player = new Player();
    song = new Song();

    jasmine.addMatchers({
        toBePlaying: function () {
          return {
            compare: function (actual, expected) {
              var player = actual;

              return {
                pass: player.currentlyPlayingSong ===
                  expected && player.isPlaying
              }
            }
          };
        }
      });
  });
Trying again starts to passing through specs, but fails on the last one:
Failures:
  1) Player #resume should throw an exception if song is already playing
    Message:
      Expected function to throw an Error, but it threw Error: song is already
      playing.
    Stacktrace:
      Error: Expected function to throw an Error, but it threw Error: song is
      already playing.
    at Object. (c:\GitHub\jsdeepdive-jasmine-and-nodejs\spec\PlayerSpec.js:71:10)
Finished in 0.007 seconds
5 Tests, 1 Failures, 0 Skipped
And this is strange, cause we for sure know that example specs should all pass. This happens because of the bug/feature of jasmine-node (don't forget it's still a Beta) and we'll change our code a bit to bypass the problem by using toThrow instead of toThrowError:
expect(function() {
  player.resume();
}).toThrowError("song is already playing");
expect(function() {
  player.resume();
}).toThrow(new Error("song is already playing"));
Hooray - it works now and all the spec pass. Yes it's a bit quirky and yes more work is needed, but it's a progress. Next time I'll show how to use Grunt, which offers a better support for Jasmine 2.0.