Tuesday, 25 April 2017

Stubbing constructors in JS

If a  constructor is exported directly from a module, it cannot be stubbed in any module that requires it directly.

For instance

========= MyConstructor.js =========
module.exports = function(){ 
  console.log('MyConstructor called'); 

and a SUT

========= MyConsumer.js =========
var MyConstructor = require('./MyConstructor');
function MyConsumer(){
    this.useful = new MyConstructor();
module.exports = MyConsumer;

You cannot stub the constructor. From my understanding the ECMAScript spec doesnt provide hooks for the new() operator. 

Lets look at some workarounds.

1) Use an init method. This involves using a constructor which calls an init() method. The init() method can then be stubbed out in the usual way. 

2) Stub the constructor using rewire

// in "dependency.js"
module.exports= function(args) {
  return new Dependency(args);

// in "foo.js"
var dependency = require('./dependency);

function foo() {
  var dep = dependency(args);
  // do stuff with dependency
exports.module.foo = foo;
and in your test:

var rewire = require("rewire"),
    foo    = rewire("../lib/foo.js");

it('should call dependency... ', function() {
   foo.__set__("dependency", /* some spy */ );


3) Dependency injection


// in "foo.js"
function foo(dependency) {
  // do stuff with dependency
exports.module.foo = foo;

// in "bar.js"
var foo = require('./foo.js')(new Dependency(args));

Wednesday, 13 July 2016

Measuring execution time

To measure the time take to run a section of code:

> console.time("toggleSeries");


> console.timeEnd("toggleSeries");

Where the parameter is any label you want.

Gives the following output: