Below is the service which get the values from web api using $resource
(function () {
'use strict';
function a($resource) {
return $resource('api/values/a');
}
angular
.module('app')
.factory('a', ['$resource', a]);}());
i have a list of services like above service
below is the service which uses the above services to get the values and it will return it as single result
How can i test the below service with jasmine unit test i need code coverage for the below service
(function () {
'use strict';
function factoryService($q, a, b, c, d) {
function fetch(id) {
var data = {},
promises = [];
data.avalues = a.query();
promises.push(data.avalues.$promise);
data.bvalues = b.query();
promises.push(data.bvalues.$promise);
data.cvalues = c.query();
promises.push(data.cvalues.$promise);
data.dvalues = d.query();
promises.push(data.dvalues.$promise);
return $q.all(promises).then(function () {
return data;
});
}
return {
fetch: fetch
};
}
angular
.module('app')
.factory('factoryService', ['$q', 'a', 'b', 'c', 'd', factoryService]);}());
can anyone help me to write unit test for above factory service with code coverage
describe('getting a,b,c,d values from service', function() {
var service,result,httpBackend,rootScope,$q,scope;
beforeEach(module('app'));
beforeEach(inject(function(proposalPlanInitialData, _$httpBackend_,$rootScope, _$q_) {
$q = _$q_;
service = proposalPlanInitialData;
httpBackend = _$httpBackend_;
rootScope = $rootScope;
scope = $rootScope.$new();
deferred = _$q_.defer();
}));
it ('should be loaded', function() {
expect(service).toBeDefined();
});
it ('should return get data when calling fetch', function() {
fakeListing = {
id: 123,
price: 300000
};
var getData = { "id": '1', "name": "dummyvalue" };
httpBackend.expectGET('api/values/a').respond({ "id": '1', "name": "dummyvalue" });
httpBackend.expectGET('api/values/b').respond({ "id": '1', "name": "dummyvalue" });
httpBackend.expectGET('api/values/c').respond({ "id": '1', "name": "dummyvalue" });
httpBackend.expectGET('api/values/d').respond({ "id": '1', "name": "dummyvalue" });
var data = service.fetch(1,1);
spyOn(service, 'fetch').and.callFake(function () {
return fakeListing;
});
// httpBackend.flush();
var data = service.fetch(1);
expect(data).toBe(fakeListing);});});
but getting a data as undefined
Related
I'm really new to Angular Unit testing using Karma and Jasmine, and I'm unable to find anything that would guide me in the right direction with regards to my problem. I have my Angular app called myApp. The app has multiple components each defined as their own modules that are then injected in the app.
App
angular.module('myApp', ['ngRoute', 'ui-bootstrap', 'dashboard', 'projects']);
Controller
angular.module('dashboard', []).controller('dashboardController',
['dashboardService', '$rootScope', '$scope', '$http', function() {
$scope.teamMemebrs = dashboardService.teamMembers;
dashboardService.getTeamMemebrs();
}]);
Service
angular.module('dashboard').service('dashboardService',
['$http', '$q', function($http, $q) {
let loadTeamMembers = () => {
return $http.get(APIendPoint).then( (response) => {
return response;
}, (response) => {
return response;
} );
};
let dashboardService = {
teamMembers : [],
getTeamMembers() {
return $q.when(loadTeamMembers()).then( (response) => {
let team = response.status === 200 ? response.data : [];
angular.copy(team, dashboardService.teamMemebrs);
});
}
};
return dashboardService;
}
]);
I am trying to test the controller and my test looks as follows, but the test fails because scope.teamMembers is undefined. What am I doing wrong?
Test Spec
describe('Dashboard', () => {
let scope, dashboardController, dashboardService, $httpBackend;
//This is what API call is expected to return
let sampleResponse = [ {name: 'Jane Doe'},
{name: 'Amy Smith'},
{name: 'John Hopkins'} ];
beforeEach(angular.mock.module('myApp'));
beforeEach(angular.mock.module('dashboard'));
beforeEach(angular.mock.inject( (_$rootScope_, _$controller_, _dashboardService_, _$httpBackend_) => {
scope = _$rootScope_.$new();
$controller = _$controller_;
dashboardService = _dashboardService_;
spyOn(dashboardService, 'getTeamMembers').and.callThrough();
dashboardController = $controller('dashboardController', { $scope: scope, dashboardService: dashboardService });
scope.$apply();
}));
it('should exist', () => {
expect(dashboardController).toBeDefined();
});
it('call dashboardService and populate scope.teamMembers', () => {
expect(dashboardService.getTeamMembers).toHaveBeenCalled();
expect(scope.teamMemebrs).toEqual(sampleResponse);
});
});
I am trying to learn how to unit test within angular. Unit testing my controllers to start with then my services.
I have started off with a basic test.
Controller code:
angular.module('app')
.controller('TestCtrl', function ($rootScope,$scope,fileLoader,ngProgress) {
$scope.test= [];
$scope.init = function(){
fileLoader.getFile("test")
.then(function(res){
//Success
console.log(res);
$scope.test= res;
}, function(err){
//Error
});
ngProgress.complete();
}
$scope.init();
$scope.title = "Test";
});
Test code:
describe('Controller: TestCtrl', function () {
// load the controller's module
beforeEach(module('app'));
var TestCtrl,
scope,test;
test = {};
test.getFile = function(name) {
return [
{
"id": 0,
"name": "Test",
"imgName": "Test.png"
},
{
"id": 1,
"name": "Test1",
"imgName": "Test1.png"
}];
};
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
TestCtrl= $controller('TestCtrl', {
$scope: scope,
fileLoader : test
});
}));
it('should have the correct title', function () {
expect(scope.title).toBe("Test");
});
});
And I can't understand why I am getting the following error:
TypeError: 'undefined' is not a function (evaluating
'fileLoader.getFile("test")
.then') undefined
Is there any way once this is resolved I can lay all my mocking out in a separate file e.g. my fileLoader mock and just inject it that way?
I don't understand how I am injecting it but yet it is undefined.
Thanks
And I can't understand why I am getting the following error:
you defined
fileLoader.getFile("test")
.then(function(res){
so getFile() should return a promise which could be resolved, but you return a simple array with two objects inside
test.getFile = function(name) {
return [
{
"id": 0,
"name": "Test",
"imgName": "Test.png"
},
{
"id": 1,
"name": "Test1",
"imgName": "Test1.png"
}]
refactor one side. Use defers or handle the array result.
I am learning AngularJS by building a small Real estate app. As i am new to AngularJS, i have very little knowledge about controller testing with many dependencies. I google about that but found very few information. Any help would be appreciated.
The following test is failing:
it('should create "proterties" model with 1 property fetched from xhr', function() {
$httpBackend.flush();
scope.properties = scope.getResultsPage(1);
expect(scope.properties).toEqual(propertiesData());
});
ControllersSpecs.js:
'use strict';
/* jasmine specs for controllers go here */
describe('Realty controllers', function() {
beforeEach(module('realtyApp'));
beforeEach(module('angularUtils.directives.dirPagination'));
beforeEach(module('realtyFilters'));
beforeEach(module('realtyServices'));
describe('PropertyListCtrl', function(){
var scope, ctrl, $httpBackend;
function propertiesData() {
return {
"total": 1,
"data":[{
"id": "26",
"property_type": "apartment",
"amount": "600",
"address": "26 Marsh St, Wolli Creek",
}]
}
};
// Learn more about dependency injection for testing
// https://docs.angularjs.org/tutorial/step_05
beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) {
$httpBackend = _$httpBackend_;
$httpBackend.expectGET('/api/properties?page=1').
respond(propertiesData());
scope = $rootScope.$new();
ctrl = $controller('PropertyListCtrl', {$scope: scope});
}));
it('should create "proterties" model with 1 property fetched from xhr', function() {
$httpBackend.flush();
scope.properties = scope.getResultsPage(1);
// scope.properties = propertiesData();
expect(scope.properties).toEqual(propertiesData());
});
});
});
Main app module:
'use strict';
/* App Module */
var realtyApp = angular.module('realtyApp', [
'ngRoute',
'angularUtils.directives.dirPagination',
'realtyControllers',
'realtyFilters',
'realtyServices'
]);
Property List controller
'use strict';
/* Controllers */
var realtyControllers = angular.module('realtyControllers', []);
realtyControllers.controller('PropertyListCtrl', ['$scope', 'Property', 'propertyImage', 'propertyData',
function($scope, Property, propertyImage, propertyData) {
$scope.beds = propertyData.beds();
$scope.bathrooms = propertyData.bathrooms();
$scope.garageSpaces = propertyData.garageSpaces();
// Paginate properties
$scope.totalProperties = 0;
$scope.propertiesPerPage = 10; // this should match however many results your API puts on one page
$scope.pagination = {
current: 1
};
$scope.getResultsPage = function getResultsPage(pageNumber) {
// The following will generate :
// http://realty.dev/api/properties?page=1
Property.get({page:pageNumber}, function(result) {
$scope.properties = result.data;
$scope.totalProperties = result.total;
});
}
$scope.getResultsPage(1);
$scope.pageChanged = function(newPage) {
$scope.getResultsPage(newPage);
};
$scope.isCarSpaceAvailable = function(carSpace) {
if (carSpace != 0) {
return true;
}
return false;
}
$scope.getPropertyImage = function(photo) {
return propertyImage.jpg(photo.name);
}
$scope.clearFilters = function() {
$scope.filter = {};
}
}]);
Edit 1:
I am getting the following error:
When you do
scope.properties = scope.getResultsPage(1);
you affect properties to what is return from getResultsPage and nothing is return from that function.
Can you try (I think flush should be call after the method) :
beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) {
$httpBackend = _$httpBackend_;
$httpBackend.whenGET('/api/properties?page=1').
respond(propertiesData());
/**** your code *****/
}));
it('should create "proterties" model with 1 property fetched from xhr', function() {
$httpBackend.expectGET('/api/properties?page=1');
scope.getResultsPage(1);
$httpBackend.flush();
// scope.properties = propertiesData();
expect(scope.properties).toEqual(propertiesData());
});
I am having a bit of trouble testing a HTTP POST in AngularJs with Jasmine.
I have a controller that looks like so:-
appControllers.controller("TaskAddController", function ($scope, $http) {
$scope.task = {};
$scope.messages = {};
$scope.actions = {
save : function() {
$http.post("/ajax/tasks/save", $scope.task)
.then(function() {
$scope.messages.success = true;
$scope.task = {};
});
}
};
});
I am testing it like so:-
describe("TaskAddController", function() {
var createController, scope, $httpBackend;
beforeEach(function () {
module('appControllers');
scope = {};
inject(function ($injector) {
$httpBackend = $injector.get("$httpBackend");
});
inject(function ($controller) {
createController = function () {
return $controller("TaskAddController", { $scope: scope });
};
});
});
afterEach(function () {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it("when actions.save is called then should call service", function () {
var task = {
title: "Title",
description: "Description"
};
$httpBackend.expectPOST("/ajax/tasks/save", task);
createController();
scope.task = task;
scope.actions.save();
$httpBackend.flush();
});
});
This causes me to get the following error Error: No pending request to flush !
What am I doing wrong?
Thanks.
What version of AngularJS are you using?
When I run the code I get: Error: No response defined !
When I add a response the test passes:
$httpBackend.expectPOST("/ajax/tasks/save", task).respond({});
What is the difference between angual.module('app') and module('app')?
Here is the simple service and unit test in question:
Service
(function () {
"use strict"
var app = angular.module('app', []);
app.service('CustomerService', ['$http', function ($http) {
return {
getById: function (customerId) {
return $http.get('/Customer/' + customerId);
}
}
}]);
}());
Test
describe('Customer Service', function () {
var $rootScope,
$httpBackend,
service,
customerId = 1;
beforeEach(function () {
angular.module('app', ['ngMock']);
inject(function ($injector) {
$rootScope = $injector.get('$rootScope');
$httpBackend = $injector.get('$httpBackend');
$httpBackend.whenGET('/Customer/' + customerId).respond({ id: customerId, firstName: 'Joe', lastName: 'Blow' });
service = $injector.get('CustomerService');
});
});
afterEach(function () {
$httpBackend.verifyNoOutstandingRequest();
});
it('should get customer by id', function () {
var customer;
service.getById(1).then(function (response) {
customer = response.data;
});
$httpBackend.flush();
expect(customer.firstName).toBe('Sam');
});
});
module in the unit test framework refers to the mock angular.mock.module method (which is attached to window as a convenience). angular.module is the method that angular.mock.module mocks.