Dependency Injection in JavaScript Tests

September 9, 2012

When you’re writing tests in Node, its often useful to be able to stub out modules which are included by the object you’re attempting to test.  Unfortunately due to the way that the module system is structured, its not straightforward to do this in a single test (as opposed to globally).

There are a few solution for this dependency injection problem around, namely node-sandboxed-module and injectr.  These modules use node’s vm module to create a new context that they run the test inside of, and in that context they use the mock instead of the original when calling `require`.  This is a nice solution, but unfortunately by bringing the code into a new context, you also break code analysis tools like mocha’s html-cov.

A few days ago, Matt Morgan released a module called mockit, which approaches the problem instead by temporarily replacing `require` when requiring the dependency the test needs (as opposed to trying to replace it for the duration of the test).

Imagine you had a `Downloader` class, and you wanted to use it in your tests, but have it so that when `Downloader` called `require(‘http’);`, it got a mock instead of node’s http class.  You could do that with one call to mockit:

var Downloader = mockit('../lib/downloader', {
  http: mockHttp
});

I think this is a really nice solution to this problem – totally unobtrusive and uses node’s existing `require` functionality when no mock exists. Check it out!

JavaScript Callstacks

September 4, 2012

Today I’m going to share a cool method for generating a JavaScript callstack from any point in your code.  JavaScript doesn’t offer this functionality, but we can tease it out pretty easily, especially in V8 (very useful for Node programmers).

The closest thing JavaScript has to a callstack is the 10-frame backtrace that comes along whenever an error is generated.  So we can use that to our advantage, by generating an error on-demand, catching the response, and examining the #stack attribute of the thrown error object:

function callstack() {
  try { capture.error } catch (e) {
    return e.stack;
  }
}

Normally we’d have to stop there, and if we wanted to access that data programatically we’d have to parse the pre-formatted String that comes back.  But with V8 we have a better option!  V8 gives us access to the method that prepares the preformatted response, so by temporarily replacing it – we can return the original data instead.  Check it out, here’s a small node.js module:

var replacementPreparer = function (error, trace) {
  return trace;
};

module.exports = function () {
  var capture;
  var oldPreparer = Error.prepareStackTrace;
  Error.prepareStackTrace = replacementPreparer;
  try { capture.error } catch (e) {
    capture = e.stack;
  }
  Error.prepareStackTrace = oldPreparer;
  return capture;
};

And the usage:

var callstack = require('./path/to/callstack/js');
for (var i = 0; i < 1000; i++) {
  callstack(); // use this anywhere in your code
}

When you call `callstack`, you’ll get back an array of CallSite objects upon which you can call methods from the V8 API to get at all the juicy details: http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi

Tags

Lazy Attributes in JavaScript

June 2, 2012

A while back, I released a tiny library called laze for making the use of lazy attributes easy in JavaScript.

I thought I’d do a post to provide some more context of how laze fits into my workflow in a node.js project.  There are definitely some terrible things you can do with this library, but hopefully this post will outline the intended use and convince you to try it out.

Imagine I want to create a new server, and then start listening on a given port.  I start out with some really tightly coupled code:

Server.prototype = {
  start: function () {
    var host = this.config.host || '127.0.0.1';
    var port = this.config.port || 8080;
    var server = http.createServer();
    server.on('request', this.handleRequest.bind(this));
    server.listen(port, host);
  }
};

This code works well, but in my opinion it just does way too much.  In here, we have logic for:

  1. Handling how to pull the host and port out of our config – and what to do if they’re not set
  2. Creating a new server
  3. Binding our server to another function for requests
  4. Starting the server listening on the given host and port

Imagine we want to start splitting this function up a bit.  We’ll start with pulling the host/port configuration out.

Server.prototype = {
  getHost: function () {
    return this.config.host || '127.0.0.1';
  },
  getPort: function () {
    return this.config.port || 8080;
  },
  start: function () {
    var server = http.createServer();
    server.on('request', this.handleRequest.bind(this));
    server.listen(this.getPort(), this.getHost());
  }
};

So this works pretty well actually – but if somewhere else in this object we’d like to have access to the host and port, we’re re-running the logic inside of `getHost` and `getPort`.  Not a big deal for these quick functions, but something that did a bit more would make that approach just wasteful.

So we could proceed in one of two ways:

Call getHost and getPort from the constructor

var Server = function () {
  this.host = this.getHost();
  this.port = this.getPort();
};

If we call the two methods from the constructor, we can have properties set that contain the proper host and port.  This is nice – but crowding our constructor with calls to methods that aren’t needed *unless* start gets called.  You can see that if these were time-intensive tasks – we’d end up wasting time for methods that may not be called at all.

Call getHost and getPort from `start`

Server.prototype.start = function () {
  this.host = this.getHost();
  this.port = this.getPort();
  var server = http.createServer();
  server.on('request', this.handleRequest.bind(this));
  server.listen(this.port, this.host);
};

This approach is good – its made our start function a bit more complicated but the separation is correct.  The one remaining problem with this approach is that if another method wants to access `host` or `port` before `start` has been called – they’ll both be undefined.

Another Option: Lazy Attributes

Laze uses `defineProperty` to give us another option.  We can define properties that won’t be set until they are used.  Then we get the best of all worlds.  The host or port can be called at any time and have the proper values.  And – once they’re called one time, they’ll hold onto their value for the next time without recomputing it.  Let’s take a look at the code:

Server.prototype = {
  start: function () {
    var server = http.createServer();
    server.on('request', this.handleRequest.bind(this));
    server.listen(this.port, this.host);
  }
};

laze.defineAll(Server.prototype, {
  port: function () {
    return this.config.port || 8080;
  },
  host: function () {
    return this.config.host || '127.0.0.1';
  }
});

If you want to – you could take this whole thing another step, and make the creation of the server lazy too.

Server.prototype = {
  this.server.listen(this.port, this.host);
};

laze.defineAll(Server.prototype, {
  port: function () {
    return this.config.port || 8080;
  },
  host: function () {
    return this.config.host || '127.0.0.1';
  },
  server: function () {
    var server = http.createServer();
    server.on('request', this.handleRequest.bind(this));
    return server;
  }
});

I hope this post gave a good overview of using lazy attributes in JavaScript with laze – if you’re interested in reading how it works check out the code (which is pretty simple), or go straight to the github page.

You can also install laze via npm:

npm install laze

Tags

Async.js is Boss

April 25, 2012

A JavaScript library I really like is async by caolan.  It makes common tasks for multiple async operations really natural, which is especially useful for Node programming.

Check it out!

Tags

Writing Node.js in CoffeeScript

April 16, 2012

Now I know I’ve spoken slightly poorly of CoffeeScript in the past, but I’ve been getting into it a bit more recently on some small libraries I’ve been writing for Node.  Turns out, it’s really easy to write parts of your Node applications in CoffeeScript and have them automatically compiled for you.

First, add “coffee-script” to your dependencies in package.json (definitely specify a real version instead of using *):

{
  ...
  "dependencies": {
    "coffee-script": "*"
  }
  ... 
}

And then, any time you need a file that’s written in CoffeeScript, just make sure you have require “coffee-script” before requiring it:

require("coffee-script");
require("./something_in_coffeescript"); // something_in_coffeescript.coffee
...

And off you go!