In my last blog post, I talked about “Test angular service using Karma and Jasmine”. Today I am going to talk about “Test angular controller using Karma and Jasmine”.
Testing Controller
Lets create a controller test file users.js and do as follows:
describe("UserController", function () {
});
Let’s mock our angular module component.users using angular.mock in the following way:
describe("UserController", function () {
beforeEach(angular.mock.module('component.users'));
});
To identify the controller users.js we need to add the dependency (inject) to our angular.mock.module in the following way:
beforeEach(inject(function (_controller_){controller = _controller_;
UsersController =controller('UsersController', {});
}));
Here we two undefined variable $controller and UsersController. Lets defined them:
beforeEach(inject(function (_controller_){
varcontroller, UsersController;
controller = _controller_;
UsersController = $controller('UsersController', {});
}));
Now lets start our first test case to check whether the controller is defined or not. To do so, follow this:
describe('UsersController', function () {
var controller, UsersController, userService;
beforeEach(angular.mock.module('component.users'));
beforeEach(inject(function (_controller){
controller = _controller_;
UsersController = $controller('UsersController', {});
}));
it (' should be defined ', function () {
expect(UsersController).toBeDefined();
});
});
Now if we run the following command:
# karma start
it will display error with controller
file name. To resolve this error lets create our controller file users.js
:
(function (){
'use strict';
angular.module('component.users', []).controller('UsersController', usersController);
usersController.$inject = []
function usersController() {
var vm = this;
}
}());
This time, you will see test case passed:
Chrome 56.0.2924 (Mac OS X 10.12.0): Executed 1 of 1 SUCCESS (0.062 secs / 0.083 secs)
TOTAL: 1 SUCCESS
Testing Controller with Service Dependency
Let’s add the dependency user-service.js
(that we created in my last blog post) to the controller and write the test for that.
First modify users.spec.js
file as follows:
describe('UsersController', function () {
var controller, UsersController, userService; // add this
beforeEach(angular.mock.module('component.users'));
beforeEach(angular.mock.module('component.users.service')); //add this
beforeEach(inject(function (_controller_, _UserService_) { // add this
controller = _controller_;
userService = _UserService_; // add this
UsersController = $controller('UsersController', {'UserService': userService}); // add this
}));
it (' should be defined ', function () {
expect(UsersController).toBeDefined();
});
});
Now if you run # karma start
you will see an error, like that
Error: [$injector:unpr] Unknown provider: UserServiceProvider <- UserService <- UsersController
To fix this error, modify users.js
controller by adding the service dependency:
(function (){
'use strict';
angular.module('component.users', []).controller('UsersController', usersController);
usersController.$inject = ['UserServic1e']
function usersController(UserService) {
var vm = this;
}
}());
This time you not see any more error.
Now lets define a method userService.all()
in service and try to access it in controller users.js
.
Update the controller test file users.spec.js
file:
describe('UsersController', function () {
var controller, UsersController, userService;
beforeEach(angular.mock.module('component.users'));
beforeEach(angular.mock.module('component.users.service'));
beforeEach(inject(function (_controller_, _UserService_){
controller = _controller_;
userService = _UserService_;
UsersController = $controller('UsersController', {'UserService': userService});
}));
it (' should be defined ', function () {
expect(UsersController).toBeDefined();
});
// add this Test Case
it('should Initlialized with a call to UserService.all()', function (){
expect(userService.all).toHaveBeenCalled();
});
});
This time if you run # karma start
, you will see an error like that:
To resolve this error we are going to use spyOn
method of Jasmine. Click here to know more about spyOn,
describe('UsersController', function () {
var controller, UsersController, userService;
beforeEach(angular.mock.module('component.users'));
beforeEach(angular.mock.module('component.users.service'));
beforeEach(inject(function (_controller_, _UserService_){
controller = _controller_;
userService = _UserService_;
spyOn(userService, 'all').and.callFake(function (){
return [{ id: '1', name: 'Masud', role: 'Developer', location: 'CA', twitter: 'masudiiuc' }];
});
UsersController = $controller('UsersController', {'UserService': userService});
}));
it (' should be defined ', function () {
expect(UsersController).toBeDefined();
});
it('should Initlialized with a call to UserService.all()', function (){
expect(userService.all).toHaveBeenCalled();
expect(userService.all()).toEqual(userList);
});
});
Now if you run # karma start
you will see the following error:
Let’s define the method in our user-service.js
file:
(function (){
'use strict';
angular.module('component.users.service', []).service('UserService', userService);
function userService() {
this.all = all;
function all(){
return [{ id: '1', name: 'Masud', role: 'Developer', location: 'CA', twitter: 'masudiiuc' }];
}
};
}());
Now if you run # karma start
you will not see any error. Now add another Test Case like that:
it('should Initlialized with a call to UserService.all()', function (){
expect(userService.all).toHaveBeenCalled();
expect(userService.all()).toEqual(
[{ id: '1', name: 'Masud', role: 'Developer', location: 'CA', twitter: 'masudiiuc' }]
); // add this
});
That’s it. Now enjoy Testing your angular application.
Help:
– Testing AngularJS with Jasmine and Karma
– Jasmine SpyOn
Continue……
If you want to explore my playground, follow this github repository: https://github.com/masudiiuc/angular-unit-test