I have an Angular App and I want to create unit test cases for it using jasmine.
In my AngularJS app, I have a service as :
var canceler;
var myServices = angular.module('myServices', ['ngResource'])
myServices.factory('getData', ['$http', '$q', function($http, $q){
var canceler;
return {
setData: function(url, callback, error) {
canceler = $q.defer();
$http.post(url, {}, {timeout:canceler.promise}).success(callback).error(error);
},
abort: function(){ canceler.resolve();}
}
}]);
This service is being used by controller.
Now how can I provide a mock for this "getData" service to the injector I am using in controllerSpecs.js (for the unit testing using jasmine).
For the reference, the code of controllerSpecs.js is defined in Getting error while using Jasmine with AngularJS.
Jasmine is a behavior development testing framework. Unit tests are written using Jasmine and are run to see if individual parts of an application are working correctly. As a result, unit tests will either pass or fail depending on if the code is working correctly or has a bug.
AngularJS is written with testability in mind, but it still requires that you do the right thing. We tried to make the right thing easy, but if you ignore these guidelines you may end up with an untestable application.
You can use AngularJS's $provide
service. This page demonstrates how to mock the functionality of a service using Jasmine's spies. Basically in your Jasmine test you can include:
var getDataMock;
beforeEach(function() {
getDataMock = {
setData: jasmine.createSpy(),
abort: jasmine.createSpy()
};
module(function($provide) {
$provide.value('getData', getDataMock);
});
});
This tells AngularJS that instead of using the real getData
service, the mock will be used in its place. In this example, using a Jasmine spy for the mock lets you easily create expectations about how and when the getData service is called by the controller. You can alternatively set getDataMock
to any other object, though it makes sense to support the same API as the real getData
service.
For bonus points, you can specify the getDataMock
object in a separate file, so that the mock may be easily used in any number of unit tests where the thing being tested uses getData
. This however requires some configuration with whatever Jasmine runner you are using.
This is all assuming you wish to unit test the controller. If you want to unit test the getData
service itself, AngularJS provides a nice mocking utility specifically for http requests.
Try something like this
//creation mock service
var mockGetData = {
data: [],
setData: function(url, callback, error){
//emulate real work, any logic can be here
data.push('called');
callback(data);
}
}
and use of the mock service
it('test description', inject(function ($rootScope, $controller){
var scope = $rootScope.$new();
var ctrl = $controller('TodoController', { $scope: scope, getData: mockGetData });
//some test here....
}))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With