AngularJS unit testing tutorial with karma-jasmine

August 3, 2015
by Rahil Shaikh

Units in your source code are small individual testable parts of your application. Unit testing is a process in which these small units of your code are tested to ensure their proper operation.

AngularJs is designed to make unit testing easier but it also depends on how you organise the code. Unit testing an application where concerns are divided into small independent units is easy rather than a piece of code that does everything.

In this tutorial we will learn to configure our Angular application for unit testing. We will also see an example on how to test custom filters.
 
This guide requires node installed, as we will be using npm to setup karma and jasmine, if you don’t have node installed then before proceeding further, get node installed.
 

Video

Watch me setting up Angular Application for unit testing with a simple example or scroll below to configuration.
 

Karma

Karma is a test runner provided by the Angular team, Karma will execute your tests in multiple browsers which shall ensure that our application is compatible in all browsers.

Jasmine

Jasmine is a javascript unit testing framework and will provide us with utilities to test our application. We can use any other javascript testing  framework for our testing but we’ll stick to jasmine as it is the most popular.

Configuration

Navigate to your working directory in your terminal or command prompt and follow the below instructions.

  • Install AngularJS
    • npm install angular --save
  • Install Karma
    • npm install -g karma --save-dev
  • Install Jasmine
    • npm install karma-jasmine jasmine-core --save-dev
  • Install ngMock
    • ngMock allows you to inject and mock angular services to help you test your application.
    • npm install angular-mocks --save-dev
  • Browsers
    • Install browser launcher on which you want karma to run your tests. We need to install atleast one browser. I’ll use PhantomJs.
    • npm install karma-phantomjs-launcher --save-dev
  • Create two folders in  your working directory.
    • mkdir app //your script files, controllers,filters etc.
    • mkdir tests //here we will keep our tests.
  •  karma.conf.js
    • karma init
    • Select Jasmine as your testing framework.
    • Select browser, I’ve selected PhantomJS.
    • Specify the paths to your js and spec files. Eg. 'app/*.js''test/*.js‘.
    • After answering a few more questions you should be done.
    • Open up your karma.conf.js and add the location of angular.js in to the files array.
      • node_modules/angular/angular.js
    • Add the location for ngMock just below that.
      • node_modules/angular-mocks/angular-mocks.js

That is about it with the configuration, now we can proceed and write our 1st test.
Note: Some commands above may require you to use sudo if you are running on linux.
Your final karma configuration file should look like this.

karma.conf.js
// Karma configuration
// Generated on Sat Jul 25 2015 19:12:21 GMT+0530 (India Standard Time)
module.exports = function(config) {
  config.set({
    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',
    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],
    // list of files / patterns to load in the browser
    files: [
      'node_modules/angular/angular.js',
      'node_modules/angular-mocks/angular-mocks.js',
      'app/app.js',  //use wildcards in real apps
      'tests/tests.js' //use wildcards in real apps
    ],
    // list of files to exclude
    exclude: [
    ],
    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },
    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],
    // web server port
    port: 9876,
    // enable / disable colors in the output (reporters and logs)
    colors: true,
    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,
    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,
    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['PhantomJS'],
    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false
  })
}

This is the minimum configuration that you’ll need to test your angular application with karma and jasmine.

Testing Pattern

 
There are a few ways to write your tests to keep it simple and organised, I’ll show you the pattern I follow.

  • Describe your object type. eg: Controller, Filters, Factory, etc.
  • Inject/load app module
  • Describe your specific object name.
  • Load mock modules as required
  • Initialize your object.
  • Describe specific method (for controllers and services)
  • Write your tests, expectations.

Unit Testing Example – Filters

Filters are easiest to test, so for this tutorial we will see an example for writing tests for a custom filter.
Lets create a custom filter and write a unit test for it to see if it is working as expected.

app/app.js – Filter Code
angular.module('MyApp', [])
.filter('reverse',[function(){
    return function(string){
        return string.split('').reverse().join('');
    }
}])

Here above if you see we have a custom filter that reverses any string passed to it. Now we need to write unit test for the filter to confirm if it is working as expected.
 

specs/tests.js – Unit test code
describe('Filters', function(){ //describe your object type
    beforeEach(module('MyApp')); //load module
    describe('reverse',function(){ //describe your app name
        var reverse;
        beforeEach(inject(function($filter){ //initialize your filter
            reverse = $filter('reverse',{});
        }));
        it('Should reverse a string', function(){  //write tests
            expect(reverse('rahil')).toBe('lihar'); //pass
            expect(reverse('don')).toBe('nod'); //pass
            //expect(reverse('jam')).toBe('oops'); // this test should fail
        });
    });
});

 
As you see above we are first describing the object type then loading our angular app. Next we are describing the object by name and initializing our filter then we write our test in the it block along with expectations.
 
To run the test in your terminal type

karma start

Improtant Update:If you are using npm v 3.x you might face some problems while running karma start. The reason is the way in which npm 3.x installs dependencies. The solution we found was to install [email protected] globally and as well as locally. Also, jasmine-core is required to be installed globally. eg: npm install jasmine-core -g

If all the tests passed you should see the below message.
 

Tests succesfull

Tests succesfull


If any of your test failed you will see the bellow message.
 
Failed test case

Failed test case

 

If you had troubles setting up karma-jasmine or running the test watch this video tutorial and follow step by step.

Conclusion

Writing unit tests for your application will make you confident about your source code and later it will speed up your development and debugging process.
In this tutorial we learnt how to set up karma and jasmine on our system to Unit test Angular Applications. We also saw an example of unit testing filters. May be in future I’ll write a post on how to unit test controllers, services and directives in AngularJS, let me know about it in the comments or on twitter.

What’s Next?

  1. Learn to write unit tests for controllers in AngularJS.

About

Engineer. Blogger. Thinker. Loves programming and working with emerging tech. We can also talk on Football, Gaming, World Politics, Monetary Systems.

Free PDF

Subscribe and get AngularJS Tips PDF. We never spam!
First Name:
Email:

45 comments

  1. A
    |

    Worthy blog

  2. |

    Thanks. great tutorial

  3. David
    |

    Great article, just a small correction, you forgot to comment the line “beforeEach(inject(function($filter){ initialize your filter” it gives parsing error I think it should be “beforeEach(inject(function($filter){ //initialize your filter”

    • |

      Yes correct, that is a comment. Thanks for reporting it.

  4. venky
    |

    Nice tutorial 🙂

  5. Aakash
    |

    Error – Can not load “PhantomJS”, it is not registered!

    • Fernando
      |

      You don’t have phantomjs installed. You should try by selecting chrome as the testing browser.

    • |

      You might have missed this command

      npm install karma-phantomjs-launcher --save-dev
  6. |

    Thanks Rahil, this helped me to set up my first test 🙂

      • |

        great tutorial… to take it further any chance on how i can show each test marked passed in the terminal almost how jasmine stand alone does in the specrunner.html ???

        • |

          Hey you can try this it will help you.
          npm install karma-spec-reporter –save-dev

  7. Victor
    |

    Hi Rahil, this tutorial is very good. I would like to ask you if you can detail the versions of dependencies to be able to run it in the same environment than yours.

    Best regards,

  8. Seshu Uggina
    |

    Great Article, Thanks..!!

  9. |

    Hi Rahil,

    I have followed steps mentioned above when i am executing karma start it will show only one success or failure.

    In my test.js file i am using code.

    it(‘Should reverse a string’, function(){ //write tests
    expect(reverse(‘ram’)).toBe(‘mar’);
    expect(reverse(‘sun’)).toBe(‘nus’);
    expect(reverse(‘rahil’)).toBe(‘lihar’); //pass
    // expect(reverse(‘don’)).toBe(‘nod’); //pass
    //expect(reverse(‘jam’)).toBe(‘oops’); // this test should fail
    });

    C:Usersmyusernameworkingproject>karma start
    15 06 2016 00:26:03.356:WARN [karma]: No captured browser, open http://localhost:9876/
    15 06 2016 00:26:03.373:INFO [karma]: Karma v0.13.22 server started at http://localhost:9876/
    15 06 2016 00:26:03.381:INFO [launcher]: Starting browser PhantomJS
    15 06 2016 00:26:05.237:INFO [PhantomJS 2.1.1 (Windows 8 0.0.0)]: Connected on socket /#S1wJhDbeQvHS29sPAAAA with id 38136700
    PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 SUCCESS (0.005 secs / 0.021 secs)

    • |

      That is correct! Your one it block is one test case, under which you put multiple expectations. If any one expectation fails, the test i.e The it block is considered to fail.

  10. |

    thanks Rahil for quick replay. This is the best article to start with Unit testing for Angular js app 🙂 .

  11. Karthik vino
    |

    “Chrome 51.0.2704 (Windows 7 0.0.0): Executed 0 of 0 ERROR (0.038 secs / 0 secs)”

    Hi Rahil, Im using git bash to run the above test and since Phantom launcher has some installing issues, I tried to run it with Chrome launcher and I get the above error. Any idea on where I went wrong ?

    Thanks for the great Article.

  12. Karthik vino
    |

    Hey Rahil, Pls dont mind the above comment. The issue got resolved and the tests worked fine 🙂 Really a great startup Sample 🙂 Thanks a ton 🙂

    • |

      Great, we are coming up with more tutorials on Unit testing. With examples for Controllers and Services. Make sure you Check them out.

  13. vasanthi
    |

    Nice Artical

  14. Noel da Costa
    |

    You have simplified this well. Thank you.
    One problem I note however is if you start injecting angular dependencies, the test break. For example if you change “angular.module(‘MyApp’, [])” to “angular.module(‘MyApp’, [‘ngSanitize’])” then the test will break.

    • |

      I have replied to your query on my other unit testing blog.
      Excuse me for replying late, was busy with other stuffs.

  15. Dave
    |

    this was a good tutorial. I did have some problems. I had to run ‘npm install -g karma-cli’ to make it work, or else I got a “No provider for ‘framework:jasmine’ error. Also, I couldn’t get phamtomjs launcher to load. Used karma-chrome-launcher instead.

    • |

      Great, these kind of comments help the other readers as well.
      I have observed there are a few issues when using the latest version of npm, its because of the way it installs the dependencies.
      I had updated the article with “Improtant Update” when I noticed it, try and see if that helps you to get running with phantomjs.

  16. pratz
    |

    I tried this just now.
    Works fine for my normal java script spec and sources file.
    But i am facing error when running angular example given above
    Uncaught ReferenceError: angular is not defined at TestController.js:1 is what i get

    TestController has below code

    angular.module(‘MyApp’, [])
    .filter(‘reverse’,[function(){
    return function(string){
    return string.split(”).reverse().join(”);
    }
    }])

    any suggestions ??
    Thanks in advance

    • |

      You need to include path to angular.js file in your files array in Karma.conf.js

    • |

      Thanks for pointing it out. Corrected it.

  17. Steve Jorgensen
    |

    Just a small thing with the example naming: instead of “it(‘Should reverse a string’,” I would say “it(‘reverses a string’,”

  18. Rupali
    |

    Thanks a lot, Rahil It helped me a lot.. As I am new to angular and so its testing too

  19. Anand Kumar
    |

    This really helped me…thanks a lot…

  20. Ankur
    |

    Nice tutorial 🙂

  21. reedynr
    |

    Nice tutorial. Thank you Rahul

  22. DINANATH S JAYASWAL
    |

    Hello Rahil,
    Can you please share more tutorials/blogs on angular jasmin karma predator mocha unit testing.
    Thanks

    • Rahil Shaikh
      |

      Hey Dinanath, will surely get more content out on this topic.

  23. |

    can anyone help me to write a test case for filter using jasmine and karma

  24. |

    How to use jquery in karma-jasmine? . I want to write script for my login page and it has written in jquery , because its store the session . it has divided in two parts like first give email id then proceed for password. I want to write script in karama jasmine . Can you please help for this.

    Thanks

Leave a Comment