Tuesday, 22 March, 2016 UTC


Summary

A friend of mine, Justin Searls, recently released a project that he and his team have been working on for a while, to replace both sinon.js and the built-in jasminebdd mock / spy tooling.
The project, TestDouble.js (apparently named after his company, TestDouble?) aims to provide a simplified, clean, yet powerful mock / stub / spy / fake / whatever-you-want-to-call-it library for use with just about any JavaScript testing framework. (Note: I’m going to call these “fakes” for the rest of this post.)
After a short conversation and reading Justin’s post announcing the library, I gave it spin and I have to say, I’m quite impressed!
Setup w/ Jasmine and Node
I’ve been a long time fan of Jasmine, and I continue to use it for my libraries and projects that need good unit testing – including the ones in Node. I use the grunt-jasmine-nodejs variant of Jasmine for node, and it works really well. 
Once I had my basic Jasmine / Grunt project structure in place, I added a “testdouble.helpers.js” file to my helpers folder:
Within this folder, I have a file that requires “testdouble” and sets it as a global name (per the project’s recommendations, and I like this idea). I also added an afterEach call to ensure testdouble cleans up any remaining fakes.
One I have that, it’s off start my tests with a very simple library.
Some Code To Test
To properly put a library like TestDouble through it’s paces, you need at least 2 things:
  1. an API that acts as a dependency
  2. code that uses the API / dependency
For example, you could create a simple object called MyMath and have it provide an “add” method.
Then, you could have another object receive an instance of MyMath as a constructor parameter, and use it in another method.
Now, when you call the “foo.doStuff()” method, it will execute the myMath.add method, as expected.
But when it comes times to write tests for the Foo object, you may want to exclude the real MyMath object. This is where TestDouble and other fakes libraries come in to play.
Testing Foo By Faking MyMath
After creating your basic Jasmine test structure, you will want to use TestDouble to create a fake MyMath instance.
The easiest way to do this with Node.js is to use the “td.object” method, passing in the original constructor function for MyMath. TestDouble will examine the prototype of MyMath and produce a “fake” version of it that can be verified:
With this fake object in hand, you can create a full test setup to exercise the code:
The code has been setup and executed at this point, so it’s on the assertions.
Assert The Behavior Of Calling MyMath
The only action that the Foo.doStuff method takes, is to call the MyMath library and it’s add function. Therefore, to ensure the behavior of Foo.doStuff is correct, you have to make an assertion that myMath.add was actually called. 
To do this with TestDouble, call the “td.verify” method, and as a single parameter, pass tell it which method and which parameters are expected by actually calling that method on the fake object.
I’m guessing TestDouble keeps track of whether or not you’re asserting something or making the real call from your code, based on the “verify” method… I’m not 100% sure how it’s doing things in the background, but I know it works.
You can see the output from your test after saving and running it:
I’m Liking It So Far
I’ve only taken a whirlwind tour of TestDouble and Jasmine, at this point, but I like what I see. The API for TestDouble appears to (mostly) simpler than Sinon, while still retaining a lot of the power and capabilities that are found in Sinon. 
The syntax is certainly different than Jasmine, for both the fake setup and verification, but I find it reads a little bit more clearly. I’ve written some pretty nasty looking behavior verifications in Jasmine in the past, and I think TestDouble will help me clean that up.
I should point out, though, that there are parts of TestDouble that don’t work in Node right now. For example, the ability to produce a completely fake, dynamically created object with “td.object” (not using a pre-defined constructor function as a parameter) requires JavaScript proxy objects. At this point, ES2015 proxies are only available in a few runtimes. 
I can also see some potential for further simplification of the API around assertions with TestDouble, but I haven’t had enough time using it to say for sure (at this point, I think have more questions than constructive feedback).
For Better Tests …
If you’re looking for an alternative to Sinon that has a simplified API, and a more powerful fake object / method library compared to Jasmine’s built in spies, check out TestDouble.js.
It already looks like it will help me with my tests, and I’m planning to use it in my current projects.