Using Angular decorators for testing

As seen in the blogpost!

by Alberto Pose

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/mocha/1.12.1/mocha.js"></script>
<script src="http://code.angularjs.org/1.1.5/angular.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/mocha/1.12.1/mocha.css">
<script src="http://chaijs.com/chai.js"></script>
<!-- We are going to use Mocha + Chai setup for testing -->
<script>
    mocha.setup('tdd');
    chai.should();
</script>
<body>
    <div id="mocha"></div>
</body>
<!-- Adding angular mocks to have 'module' and 'inject' functions -->
<script src="http://code.angularjs.org/1.1.5/angular-mocks.js"></script>

JavaScript

/*
# Using decorators for unit testing

The idea behind this simple app is to show how to use Decorators in Angular to do unit testing.
In this case we have two factories: One called parent and the other child. What we want to achieve is write unit tests for the child factory instance. 

Here is a simple Angular module that contains both parent and child:
*/

angular.module('myApp', [])
.factory('greeter', function () {
    return 'Hello';
})
.factory('worldGreeter', function (greeter) {
    return greeter + ' World';
});

/* As you can see, child is concatenating the input from parent.

So let's write some tests using mocha:
*/
describe('worldGreeter', function () {
    var worldGreeter;

    /* We are including myApp module for testing */
    beforeEach(module('myApp'));
    
    /* We are replacing parent with our own implementation.
    $delegate is a reference to the old parent instance. $delegate 
    is really helpful if you plan mocking or stubbing it using a framework
    like sinon. */
    beforeEach(module(function ($provide) {
        $provide.decorator('greeter', function ($delegate) {
            return 'Bye';
        });
    }));

    /* Here we have another angular trick, we name the instance _child_
    so we can have a variable named child on the describe scope. inject recognizes
    this and injects the proper instance allowing the usage of the more handy child
    variable. */
    beforeEach(inject(function (_worldGreeter_) {
        worldGreeter = _worldGreeter_;
    }));

    /* Finally, we can see the assertion that parent was
    replaced successfully */
    it('should work with mocked greeter', function (done) {
        worldGreeter.should.be.equal('Bye World');
        done();
    });
});

mocha.run();

/* To sum up, great things can be achieved with decorator in what test is related. Although
there is little documentation on that feature, it is really useful when having to replace an instance dependencies. */