Javascript: testing mediators using sinon and inject-loader

Unit testing in javascript is not always easy, especially when it comes to testing asynchronous code. And searching the internet might not always give you an answer or, at least, the best answer…

I personally like the mediator pattern and I use it a lot in my projects. Mediators allow you to decouple your front-end components from your services, and by doing so, testing all the different parts of your application becomes easier.

structure of the Mediator pattern

I like to use Postal.js for communication between the different parts of my applications, especially between the front-end components, the mediators and the services. Postal.js is a very well known in-memory message bus inspired by AMQP and allows you to post and subscribe to messages in a very simple fashion.

Now, testing front-end components and services is relatively straightforward, but testing mediators is not so easy. And the reason is that you mediators will normally call services to do some kind of logic, and you need to mock those services, which is not trivial if you’re using bundlers like webpack or requirejs.

If you’re using webpack, fortunately, a very simple library is available that allows you to mock the required dependencies that your mediator uses. So if you imagine you have a service like this:

//myService.js
exports default () => {
    this.doWork = () => {
        return 'doing some work...';
    }
}

and a mediator like this:

//myMediator.js
import postal from 'postal';
import myService from 'myService';

var channel = postal.channel('channel.name');

channel.subscribe('topic.name', () => {
       console.log(myService.doWork()); // doing some work...
});

Then you can easily test this mediator like this:

//myMediator-test.js

var postal = require('postal');
var sinon = require('sinon/pkg/sinon');
var expect = require('chai').expect;

describe('My mediator', function(){
      var myServiceStub, myServiceMock;
      var channel = postal.channel('channel.name');

      beforeAll(function(){
            var MyModuleInjector = require('inject!myMediator');
            
            //Create stub for doWork
            myServiceStub = sinon.stub().returns('Mock do work...');

            //Creating mock to be injected
            myServiceMock = function (){
                 this.doWork = myServiceStub;
            });

            //Injecting the mock
            MyModuleInjector({
                   'myService': myServiceMock
            });
      });

      it('should use mock service', function(){
         channel.publish('topic.name');
         expect(myServiceStube.called).to.be.true;
      });
});

Some clarifications about the code above.

First, in the mediator test where I do something like require(‘inject!myMediator’), I’m using the inject-loader an awesome webpack loader that allows you to mock your required dependencies. With the inject loader you can mock all or just the dependencies you want, which makes it extremely flexible!

Second, I’m using sinon to create my stubs, because it’s an amazing library for stubbing, mocking and spying. Really, if you don’t know what it is you should look it out, it is extremely easy to use and is agnostic to your application infrastructure, so you can always use it.

As you see, if you’re using webpack, testing your mediators should be simple enough, and now you don’t have an excuse not to test them. 🙂

From Requirejs to Webpack, the old and the new…

requirejswebpack

 

As you already figured out by the title, this post will try to show you why I and my team decided to move from requirejs to webpack. They are both widely used and requirejs is clearly the oldest of the two, hence, this is somehow comparing the old with the new.

And, for me at least, in this case, old doesn’t mean gold :). Don’t get me wrong, requirejs was a great library when it was built and set the standards for many of the similar bundlers that came after, like webpack.

But in my experience requirejs is not dealing well with how new web applications are evolving, and I’ll try to explain, according to my experience using the tool, why we decided to move to webpack.

Why move:

Well, we first started thinking about moving from requirejs to webpack after we started extracting modules from a big application we had into separate npm modules. Because requirejs doesn’t import node modules, we had to start “hacking” and we installed our private npm modules into a folder inside the source path of our application so that they could be bundled by requirejs.

Well this has a lot of problems, first we don’t want a separate folder inside our source folder just to have external dependencies imported by requirejs. Second, if any of these modules has a dependency on a module that is already installed in the outer “primary” node_modules folder you would end up with that dependency being installed twice.

Webpack was built to support NPM modules, so you don’t have to worry about placing node modules inside the application source folder.

Requirejs follows the AMD (Asynchronous Module Definition) proposal, which for anyone used to work with node and CJS (CommonJS) modules can be annoying. They provide a way to convert CJS into AMD, but is really not flexible, and you have to follow specific steps to make it work, and really why should we care about that anyway, it should be transparent to us.

Webpack supports both AMD and CJS, so you don’t have to worry about converting AMD to CJS or vice versa, it just works. You might think that this is not a big deal, but when you think that you can use any nodejs library in the browser out of the box, things start to get exciting.

Another problem with requirejs is the loaders plugins. I really don’t want to explicitly have to do something like this:

define(['css!styles/cssfile'], function() { /* .. */})

Applying processors explicitly is not a good idea, it should be a responsibility of the bundler to detect different types of files and process them in the background, and it should be transparent to you.

Webpack loaders are really amazing, configuring the loaders is really simple and the overall plugin system is more robust. Also, ES6 support is very easy to add with the babel-loader in webpack, while making ES6 to function in requirejs is a little bit of a battle.

Conclusion:

For all this, we decided to take the hit of converting a big application from requirejs to webpack, but I think it is the right thing to do and will undoubtedly pay off in the future.