Stub private functions in an ES6 module

Local/private functions are always hard to test in isolation. This post explores the potential ways to solve that problem.

Lets say you have a module which looks like this.
+run.js:

function _one() {
	// do something big
}
function runThing() {
	return _one();
}
export {
  _one,
  runThing as default,
};

You want to test runThing() and _one() in isolation how can you do this using Sinon stubs?
The below will not work.

import * as run;
sinon.stub(run, ‘_one’) // => doesnt do anything...not same instance.
run.default();

You could swap to using a Class.

export default Class Run {
	_one() {
		// something big
	}
	thing() {
		return this._one()
	}
}

Now we are working off an instance and your test would look like this:

import Run;
run = new Run(); // <- 1 extra line...is that so bad? ;) 
sinon.stub(run, ‘_one’) // => stubbed !!
run.thing();

However swapping your nice ES6 module to a Class just for testing is a horrendous idea. Instead try making use of the “modular” side of modules.
i.e. split our function into a seperate module, its heavy after all.
+thingUtil.js

export function one() {
	// something big
}

Now import it and run it from there.
+runThing.js

import { one } 


export default function runThing() {
	return one();
}

Now our test will look like (pseudo form):

import runThing
proxyquire: { one: oneStub } => can hand it a new dependent
runThing()

We can use proxyquire to stub the dependency and control and test everything about run.js. Next we will be able to do the same for one().

Modules are meant to be composable/isolated and encourage simple interfaces and interactions.

Leave a Reply