3

I am using jasmin to test my AngularJs project with following code

controllersSpec.js

describe('myApp', function(){

    beforeEach(angular.mock.module('myApp'));

    it('should have a mailctrl', function() {
        expect(myApp.mailctrl).toBeDefined();
    });
});

controller.js

var myApp = angular.module('myApp', []);

myApp.controller('mailctrl', ['$scope', '$routeParams', '$rootScope', 'getMailData', '$angularCacheFactory',

    function ($scope, $routeParams, $rootScope, getMailData, $angularCacheFactory) {
           ##....controller content....##
    }
]);

SpecRunner.html

<script type="text/javascript" src="../lib/angular/angular.min.js"></script> <script type="text/javascript" src="lib/jasmine-2.0.0/jasmine.js"></script> <script type="text/javascript" src="lib/jasmine-2.0.0/jasmine.js"></script> <script type="text/javascript" src="lib/jasmine-2.0.0/jasmine-html.js"></script> <script type="text/javascript" src="lib/jasmine-2.0.0/boot.js"></script> <script type="text/javascript" src="../test/lib/angular/angular-mocks.js"></script> <script src="../js/controller.js"></script> <script src="../test/unit/controllersSpec.js"></script>

Now when I am opening Specrunner.html in browser, I am getting following error

Expected undefined to be defined.
I have following question regarding above

1) Where I am getting wrong ?
2) How can I use $rootScope variable of controller ?
3) Whats the difference in beforeEach(angular.mock.module('myApp')); and beforeEach(angular.module('myApp')); and beforeEach(module('myApp'));

EDIT :

I have modified the code as

describe('myApp', function(){
    beforeEach(angular.mock.module('myApp'));        
    it('should have a mailctrl', inject(function($rootScope, $controller) {
        var controller = $controller('mailctrl', { $scope: $rootScope.$new(), $rootScope: $rootScope });
        expect(controller).toBeDefined();
}));

and getting following error -

Error: [$injector:unpr] http://errors.angularjs.org/undefined/$injector/unpr?p0=%24routeParamsProvider%20%3C-%20%24routeParams

If I add other params in $controller() (i.e. '$routeParams', 'getMailData') Error comes as they are undefined.

1 Answer 1

7

1) You are making a mistake by trying to access your controller as a field on a module. in your test you should be injecting $controller into your test to create your controller. What that means is that you should be writing your tests like the following:

it('should have a mailctrl', inject(function($rootScope, $controller) {
   var controller = $controller('mainctrl', { $scope: $rootScope.$new(), $rootScope: $rootScope, ...  }) // rest of your dependencies
   expect(controller).toBeDefined();
}));

2) See 1

3) angular.mock.module is used to register your module to the injector in your tests. It is the same thing as module. angular.module is used to create, register or retrieve a module for your application.

Regarding your edit:

You are not providing routeParams and any other service that your controller depends on so $injector does not know where to get them from and is throwing this error. $injector has to know what to inject for every parameter that is required by your controller. Your controller depends on

  • $rootScope: provided by angular
  • $scope: can be created by $rootScope.$new()
  • getMailData: This is your service, you have to provide a mock for this
  • $routeParams: This is angular built-in structure but there is not a dedicated mock, but since it is a very simple object you can provide a mock for this yourself.
  • $angularCacheFactory: this is a third party service and you have to provide a mock for this as well

So in the end you should be creating your controller like this:

it('should have a mailctrl', inject(function($rootScope, $controller) {
   var controller = $controller('mainctrl', { 
         $scope: $rootScope.$new(), 
         '$routeParams': {}, // whatever  it needs to be to be able to test your controller
         $rootScope: $rootScope, 
         'getMailData': getMailDataMOCK // this object is created by you in your test code
         '$angularCacheFactory': $angularCacheFactoryMOCK
       }) 
   expect(controller).toBeDefined();
}));

If you don't provide any of these arguments then it will try to get it from $injector and will throw an exception when not found.

Sign up to request clarification or add additional context in comments.

3 Comments

I have modified code as you told and got this - "Error: [$injector:unpr] errors.angularjs.org/undefined/$injector/… in localhost/startmail/lib/angular/angular.min.js (line 6)"
hey @idursun please suggest, although I am getting your point yet it's still not working.
How did you modify your code? Can you update your question with the latest code?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.