28

Basically, I'm quite experienced with Mocha (written thousands of unit tests), and I'm quite new to AngularJS (written just my first project).

Now I am wondering how I might unit test all the AngularJS stuff using Mocha.

I know that Mocha runs in the browser, and I have already done this. But how do I structure and setup things?

I guess I need to:

  • Load AngularJS
  • Load Mocha
  • Load my tests

Within each of the tests, I need to load a controller, a service, ... to test. How do I do that? I am not using require.js or something like that, the files are just script files with basically the following content:

angular.controller('fooController', [ '$scope', function ($scope) {
  // ...
}]);

How do I reference and instantiate that controller within a test? The same holds true for services, directives, ...

Do I need to create mocks for $scope, $http & co. for myself, or is there some help?

Please note that I am aware that there is the Karma test runner (formerly known as Testacular), but I do not want to switch my test runner completely.

3
  • 1
    Even though you're not using Karma/Testacular, take a look at some of the examples in angular-seed. They show how you use angular-mocks to set up your modules for testing. Commented Apr 30, 2013 at 6:49
  • 4
    This is quite a useful article for testing using mocha: yearofmoo.com/2013/01/… Commented Jun 5, 2013 at 11:28
  • 2
    the angular-seed project isnt very helpful as it is using jasmine. Why aren't there examples using mocha and its adapter? Commented Jul 31, 2013 at 0:53

2 Answers 2

14

One way of doing that is to use Angular $injector in your tests:

myModule_test.js

suite('myModule', function(){
  setup(function(){
    var app = angular.module('myModule', []);
    var injector = angular.injector(['myModule', 'ng']);
    var service = injector.get('myService');
  });

  suite('myService', function(){
    test('should return correct value', function(){
       // perform test with an instance of service here
    });
  });
});

your html should look similar to this:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>myModule tests</title>
  <link rel="stylesheet" media="all" href="vendor/mocha.css">
</head>
<body>
  <div id="mocha"><p><a href=".">Index</a></p></div>
  <div id="messages"></div>
  <div id="fixtures"></div>
  <script src="vendor/mocha.js"></script>
  <script src="vendor/chai.js"></script>
  <script src="angular.min.js"></script>
  <script src="myModule.js"></script>
  <script>mocha.setup('tdd')</script>
  <script src="myModule_test.js"></script>
  <script>mocha.run();</script>
</body>
</html>
Sign up to request clarification or add additional context in comments.

Comments

3

If you're creating an angular service that doesn't have any dependencies and isn't necessarily angular specific, you can write your module in an angular-agnostic way, then either write a separate small angular wrapper for it, or test for the presence of angular, and conditionally create a service for it.

Here's an example of an approach that I use to create modules that can be used both in angular, the browser, and node modules, including for mocha tests:

(function(global) {
    //define your reusable component
    var Cheeseburger = {};

    if (typeof angular != 'undefined') {
        angular.module('Cheeseburger', [])
            .value('Cheeseburger', Cheeseburger);
    }
    //node module
    else if (typeof module != 'undefined' && module.exports) {
        module.exports = Cheeseburger
    }
    //perhaps you'd like to use this with a namespace in the browser
    else if (global.YourAppNamespace) {
        global.YourAppNamespace.Cheeseburger = Cheeseburger
    }
    //or maybe you just want it to be global
    else {
        global.Cheeseburger = Cheeseburger
    }
})(this);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.