testing wrapped $http angularjs - angularjs

I am using angularjs and i have to test wrapped $http
ang.factory("HttpService", ["$http", "$q", function ($http, $q) {
return {
get: function (url) {
var result = $q.defer();
$http.get(url).success(function ($data) {
result.resolve($data);
}).error(function ($data) {
result.reject($data);
});
return result.promise;
}
};
}]);
And i think test should be something like
beforeEach(module('ngBoilerplate.employee', function ($provide) {
HttpService = jasmine.createSpyObj("HttpService", ["get", "post"]);
$provide.value("HttpService", HttpService);
}));
beforeEach(inject(function (_$controller_, _$rootScope_, _HttpService_) {
$scope = _$rootScope_.$new();
HttpService = _HttpService_;
$controller = _$controller_('EmployeeCtrl', {$scope: $scope, HttpService: HttpService});
}));
PS: I am using ngBoilerplate.
Thanks

Related

Angular/Jasmin promise unit test not working

The following Angular controller works fine:
angular.module("mymodule", [])
.service('svc', function($q) {
this.call = function() {
return $q.when(3);
};
})
.controller('MainCtrl', function($scope,svc) {
svc.call()
.then(function successCallback(response) {
$scope.var1 = response;
console.log($scope.var1);
});
});
However the related Jasmin unit test returns an error:
describe('Testing a Controller that uses a Promise', function () {
var $scope;
var $q;
var deferred;
beforeEach(module('mymodule'));
beforeEach(inject(function($controller, _$rootScope_, _$q_, svc) {
$q = _$q_;
$scope = _$rootScope_.$new();
deferred = _$q_.defer();
spyOn(svc, 'call').and.returnValue(deferred.promise);
$controller('MainCtrl', {
$scope: $scope,
svc: svc
});
}));
it('should resolve promise', function () {
deferred.resolve(11);
$scope.$apply();
expect($scope.var1).toBe(11);
});
The error:
TypeError: undefined is not a constructor (evaluating 'svc.call()
.then(function successCallback(response) {
$scope.var1 = response;
console.log($scope.var1);
})') in test/cookbook2.js (line 11)
Any ideas how to fix this problem?
PLUNK: http://plnkr.co/edit/j8J8J31ver1IE3fl6GyY?p=preview

Unit test controller with injected service

I want to test that my injected service is being called in my controller.
login.controller.js
angular.module('exampleModule')
.controller('LoginCtrl', ['$state', 'AuthService',
function($state, AuthService) {
var self = this;
self.submit = function() {
AuthService.login(self.credentials)
.then(function(res) {
console.log('success');
$state.go('home');
}, function(res) {
if (res.status === 400) {
console.log('error')
}
});
};
}
]);
login.service.js
angular.module('exampleModule')
.factory('AuthService', ['$http',
function($http) {
var authService = {};
authService.login = function(credentials) {
return $http.post('/api/authenticate', credentials);
.then(function(res) {
return res;
});
};
return authService;
}
]);
login.controller.test.js
describe('Controller: LoginCtrl', function() {
beforeEach(module('exampleModule'));
var ctrl, authService;
beforeEach(inject(function($controller, AuthService){
ctrl = $controller('LoginCtrl');
authService = AuthService;
}));
describe('submit function', function() {
beforeEach(function(){
ctrl.submit();
});
it('should call AuthService', function() {
expect(authService.login).toHaveBeenCalled();
});
});
});
How do I properly test whether AuthService.login was called? With the way I'm injecting the AuthService into my test, I'm getting these errors:
TypeError: 'undefined' is not an object (evaluating 'AuthService.login(self.credentials).then')
You need to mock the login() method and make it return a promise:
describe('Controller: LoginCtrl', function() {
beforeEach(module('exampleModule'));
var ctrl, authService, $q;
beforeEach(inject(function($controller, _$q_, AuthService){
ctrl = $controller('LoginCtrl');
$q = _$q_;
authService = AuthService;
}));
describe('submit function', function() {
beforeEach(function(){
var deferred = $q.defer();
spyOn(authService, 'login').and.returnValue(deferred.promise);
ctrl.submit();
});
it('should call AuthService', function() {
expect(authService.login).toHaveBeenCalled();
});
});
});
Working Plunker

Jasmine Unit Test for http

I am trying to write unit tests cases around an Angular service. What I am basically trying to test is that the http request is made.
Service
app.service("myService", [
"$http", function ($http) {
this.result = "initial value";
this.get = function (param1, param2) {
return $http({
method: "GET",
url: "api/someService/Get/" + param1 + "/" + param2
})
.success(function (data) {
this.parent.result = data;
console.log(data);
console.log(this.parent.result);
return data;
})
.error(function () {
return "Error occurred";
})
;
};
}
]);
Below is what I have tried.
describe("Surcharge Increase Formula", function () {
var controller;
var scope;
var httpBackend;
var myService;
beforeEach(inject(function($controller, $rootScope, $httpBackend, _myService_) {
scope = $rootScope.$new();
httpBackend = $httpBackend;
myService = _myService_;
});
it('waiver service makes API call', function () {
var response = "This is the response";
httpBackend.when('GET', "api/SurchargeWaiver/Get/0/0").respond(response);
waiverService.get(0, 0);
//httpBackend.flush();
expect(waiverService.result).toEqual(response);
});
What I would like to do is make a call similar to expect(...).toHaveBeenCalled() to see if the api call has been made, or any other way to just test the http call.
Any suggestions?

Mocking HTTP service unit test with AngularJS and Jasmine

I am attempting to build a mock service so that my unit tests can verify certain functions are called and updated accordingly. Unfortunately I cannot get this to work.
Im currently getting an error undefined is not a function on this line:
spyOn(statusService, 'getModuleStatus').andCallThrough();
My actual service looks like this:
serviceStatusServices.factory('serviceStatusAppAPIservice', function ($http) {
var serviceStatusAppAPI = {};
serviceStatusAppAPI.getModuleStatus = function () {
return $http({
method: 'JSON',
url: '/settings/getservicestatusandconfiguration'
});
}
serviceStatusAppAPI.setModuleStatus = function (module) {
return $http({
method: 'POST',
url: '/settings/setservicestatusandconfiguration',
data: { moduleId: module.ModuleId, configData: module.ConfigValues }
});
}
return serviceStatusAppAPI;
});
My update function
serviceStatusControllers.controller('serviceStatusController', ['$scope', 'serviceStatusAppAPIservice', '$filter', '$timeout', function ($scope, serviceStatusAppAPIservice, $filter, $timeout) {
$scope.update = function () {
$scope.loading = true;
serviceStatusAppAPIservice.getModuleStatus().then(function (response) {
$scope.modules = $filter('orderBy')(response.data.moduleData, 'ModuleName')
...
My tests look like this
describe('ServiceStatusController', function () {
beforeEach(module("serviceStatusApp"));
var scope;
var statusService;
var controller;
var q;
var deferred;
// define the mock people service
beforeEach(function () {
statusService = {
getModuleStatus: function () {
deferred = q.defer();
return deferred.promise;
}
};
});
// inject the required services and instantiate the controller
beforeEach(inject(function ($rootScope, $controller, $q) {
scope = $rootScope.$new();
q = $q;
controller = $controller('serviceStatusController', {
$scope: scope, serviceStatusAppAPIservice: statusService });
}));
describe("$scope.update", function () {
it("Updates screen", function () {
spyOn(statusService, 'getModuleStatus').andCallThrough();
scope.update();
deferred.resolve();
expect(statusService.getModuleStatus).toHaveBeenCalled();
expect(scope.modules).not.toBe([]);
});
});
});
Also, how do I pass any mock data returned from the service to the caller. Currently in my model I do serviceStatusAppAPI.getModuleStatus(data) then use data.Data to get out the returned JSON.
I assume if you are doing something like this in your ctrl
scope.update = function() {
serviceStatusAppAPIservice.setModuleStatus(url).then(function (data) {
scope.modules = data;
})
};
Service which returns promise
.factory('serviceStatusAppAPI', function($http, $q) {
return {
getModuleStatus: function() {
var defer = $q.defer();
$http({method: 'GET', url: '/settings/getservicestatusandconfiguration'})
.success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
defer.resolve(data);
})
.error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
window.data = data;
});
return defer.promise;
}
};
});
So in you controller you will get data like this
serviceStatusAppAPI.getModuleStatus().then(function (data) {
$scope.modules = $filter('orderBy')(data.moduleData, 'ModuleName')
})
This is how you can run your unit test case
beforeEach(function() {
var statusService = {};
module('myApp', function($provide) {
$provide.value('serviceStatusAppAPIservice', statusService);
});
statusService.modalStatus = {
moduleData: [{ModuleName: 'abc'}, {ModuleName: 'def'}]
};
inject(function ($q) {
statusService.setModuleStatus = function () {
var defer = $q.defer();
defer.resolve(this.modalStatus);
return defer.promise;
};
statusService.getModuleStatus = function () {
var defer = $q.defer();
defer.resolve(this.modalStatus);
return defer.promise;
};
});
});
beforeEach(inject(function ($rootScope, $controller, _$stateParams_) {
scope = $rootScope.$new();
stateParams = _$stateParams_;
controller = $controller;
}));
var myCtrl = function() {
return controller('ServiceStatusController', {
$scope: scope,
});
};
it('should load status', function () {
myCtrl();
scope.update();
scope.$digest();
expect(scope.modules).toBe({
status: 'active'
});
});

Jasmine error when using $httpBackend

I'm using Jasmine in Visual Studio with chutzpah test adapter on top of AngularJs.
I get this error when running the test:
Error: Unexpected request: GET /webapi/api/Map
Error: Unsatisfied requests: GET /webapi/api/Map/
service:
var services = angular.module('mapService', ['ngResource']);
services.factory('mapService', ['$resource',
function ($resource) {
var objects = undefined;
var res = $resource('/webapi/api/Map/', {}, {
query: {
method: 'GET',
isArray: true
}
});
return {
getObjects: function (callback) {
res.query(function(successResult) {
objects = successResult;
});
return objects;
}
}
}]);
test:
describe('testing the department controller', function () {
var $scope, $location, mapController, $httpBackend, myMapService;
beforeEach(module('app'));
beforeEach(inject(function ($injector, $rootScope, $controller, _$httpBackend_, mapService) {
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', '/webapi/api/Map/')
.respond([jasonArray]);
myMapService = mapService;
}));
afterEach(function () {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('should have objects', function () {
$httpBackend.expect('GET', '/webapi/api/Map/');
var objects = myMapService.getObjects(function (result) {
objects = result;
});
$httpBackend.flush();
expect(objects.length).toBeGreaterThan(0);
});
});
Can anyone suggest what I'm missing?
The error was in the url:
Just removed the trailing slash and it worked fine.
$httpBackend.when('GET', '/webapi/api/Map')

Resources