× {{alert.msg}} Never ask again
Get notified about new tutorials RECEIVE NEW TUTORIALS

Simplify JS Testing with Factories

Josh David Miller
Feb 04, 2016
<p>Unit testing requires that our components have clear separation of concerns. But what if we have a dependency on an external library?</p> <pre><code class="language-javascript">// index.js const library = require( 'Library' )( args ); function myFunction ( arg1, arg2 ) { library.someMethod(); }; myFunction();</code></pre> <p> </p> <p>How might we go about testing <code>myFunction</code> without making calls to the library or managing its side effects? You could use a dependency injection library (such as <a href="https://www.npmjs.com/package/administer">the one I wrote</a>), but the simplest solution is to just to split up the code and use factories:</p> <pre><code class="language-javascript">// my-function.js module.exports = function MyFunction ( library ) { return function myFunction ( arg1, arg2 ) { library.someMethod(); }; }; // index.js const library = require( 'Library' )( args ); const myFunction = require( './my-function' )( library ); myFunction();</code></pre> <p> </p> <p>Now when we want to test our function, we can simple mock it out. Using mocha, sinon, and assert, that might look like this:</p> <pre><code class="language-javascript">// my-function.spec.js const assert = require( 'assert' ); const sinon = require( 'sinon' ); const MyFunction = require( './my-function' ); describe( 'MyFunction', function () { beforeEach( function () { this.LibraryMock = { someMethod: sinon.spy(), }; }); it( 'should return a function', function () { const expected = 'function'; const actual = typeof MyFunction( this.LibraryMock ); assert( actual == expected ); }); describe( 'myFunction instance', function () { beforeEach( function () { this.myFunction = MyFunction( this.LibraryMock ); }); it( 'should call library.someMethod()', function () { this.myFunction(); const expected = true; const actual = this.LibraryMock.someMethod.called; assert( expected == actual ); }); }); });</code></pre> <p> </p> <p>This results in far cleaner code that is easier to test and is more scalable and durable. Happy hacking!</p>
comments powered by Disqus