Given the following test.
The $provided service is not being injected. If I debug the test in karma I can see that the service being provided is the real one, and not the mock.
The really weird thing, is that if I remove the $provide.service... I get an error Error: [$injector:unpr] Unknown provider: ficaServiceProvider <- ficaService. This clearly means that the service is getting registered, just not replaced?
describe("component: FicaStatusComponent",
function () {
var fs;
beforeEach(function () {
module("aureus",
function ($provide) {
$provide.service("ficaService", function () {
this.status = function () {
return $q(function (resolve, reject) {
resolve([{ documentType: { id: 1 } }]);
});
}
})
});
});
beforeEach(inject(function (_$componentController_, _ficaService_) {
$componentController = _$componentController_;
fs = _ficaService_;
}));
it("should expose a `fica` object", function () {
console.log('should expose');
var bindings = {};
var ctrl = $componentController("ficaStatus", null, bindings);
expect(ctrl.fica).toBeDefined();
});
it("compliant with no documents should not be compliant",
function () {
var ctrl = $componentController("ficaStatus");
expect(ctrl.fica.length).toEqual(1);
});
}
);
The second test compliant with no documents... is failing.
Chrome 56.0.2924 (Windows 10 0.0.0) component: FicaStatusComponent compliant with no documents should not be compliant FAILED
Error: Unexpected request: GET api/fica/status/
I have also tried this, expecting to have an empty object injected, but the "real" service is there nevertheless?
module("aureus", function($provide) {
$provide.value("ficaService", function() { return {}; });
$provide.service("ficaService", function() { return {}; });
});
Here is the implementation of the controller for the component:
var FicaStatusController = (function () {
function FicaStatusController($log, $loc, ficaService) {
var _this = this;
this.$log = $log;
this.$loc = $loc;
this.ficaService = ficaService;
this.fica = [];
this.ficaService.status(1234).then(function (_) { return _this.fica = _; });
}
FicaStatusController.$inject = ["$log", "$location", "IFicaStatusService"];
module("aureus").component("ficaStatus", new FicaStatusComponent());
module("aureus").service("IFicaStatusService", FicaStatusService);
The service is as follows:
var FicaStatusService = (function () {
function FicaStatusService($log, $http) {
this.$log = $log;
this.$http = $http;
}
FicaStatusService.prototype.status = function (accountNumber) {
var url = "api/fica/status/" + accountNumber;
this.$log.log("status: " + url);
return this.$http
.get(url)
.then(function (_) { return _.data; });
};
return FicaStatusService;
}());
...
You have added your service in your module like this:
module("aureus").service("IFicaStatusService", FicaStatusService);
That means that you will need to provide IFicaStatusService instead of ficaService with $provide.
Related
I am trying to Unit Test an AngularJS HTTP Service with the help of Karma-Jasmine.
But I am facing the following Error from Karma:
Error: Unexpected request: GET app/license/license.html
I Googled and found out that it has something to do with ui-router.
The following StackOverflow Link: (UI-router interfers with $httpbackend unit test, angular js) suggests some Answers, but none of them works for me and the Error remains the same.
I am posting my code below for reference:
licensedata.service.js
(function () {
"use strict";
angular
.module("app")
.factory("licenseDataService", licenseDataService)
licenseDataService.$inject = ["$http"];
function licenseDataService($http) {
return {
getLicenseSpecs: getLicenseSpecs
};
function getLicenseSpecs() {
return $http.get("http://localhost:8080/?command=print-spec")
.then(success)
.catch(fail);
function success(response) {
return response.data;
}
function fail(e) {
return e.data;
}
}
}
})();
licensedata.service.spec.js
describe("LICENSE DATA SERVICE", function () {
var licenseDataService;
var httpBK;
beforeEach(angular.mock.module("app"));
beforeEach(angular.mock.module(function ($urlRouterProvider) {
$urlRouterProvider.deferIntercept();
}));
beforeEach(inject(function (_licenseDataService_, $httpBackend) {
licenseDataService = _licenseDataService_;
httpBK = $httpBackend;
}));
it("Test License Key", function () {
var returnData = {};
httpBK.expectGET("http://localhost:8080/?command=print-spec").respond(returnData);
var returnedPromise = licenseDataService.getLicenseSpecs();
var result;
returnedPromise.then(function (response) {
result = response.data;
});
httpBK.flush();
});
});
Any help will be greatly appreciated.
After building the Web API, I just promoted a controller to a service (.factory) to share that data with other controllers in AngularJS.
However it seems that I have a syntax error and the factory is not accepted as it.
This is my App.js:
//appContacts.js
(function () {
"use strict";
var app = angular.module("appContacts", ["simpleControls", 'ui.router', 'ngResource'])
.config(a lot of stuff here)
.factory('ContactService', function ($resource) {
var ContactService = {};
var vm = this;
vm.contacts = [];
vm.newContact = {};
vm.errorMessage = "";
vm.isBusy = true;
// Load all contacts
ContactService.getContacts = function () {
return $resource.get("api/contacts")
.then(function (response) {
angular.copy(response.data, vm.contacts);
}
);
};
//Set Current Contact
ContactService.setCurrentContact = function (contact) {
vm.currentContact = contact;
return vm.currentContact;
};
return ContactService;
})
})();
and this is my contatcsController:
//contactsController.js
(function () {
"use strict";
angular.module("appContacts")
.controller("contactsController", function (ContactService) {
//Get all Contacts
ContactService.getContacts = function () {
vm.contacts = contacts;
}
vm.setCurrentContact = function (contact) {
vm.currentContact = contact;
};
})
})();
I keep getting this error: Possibly unhandled rejection: {} in the Console and nothing shows in the front end.
Does anybody has an idea why it does not work as factory the same code that worked inside the controller?
More details at https://github.com/angular-ui/ui-router/issues/2889
app.config(['$qProvider', function ($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}]);
I'm following John Papa's Angular Style guide for creating a small application, and I can't seem to work out an issue with the controller using a method from a service...
module
(function () {
'use strict';
var accountsApp = angular.module('accountsApp', ['ui.bootstrap', 'ngAnimate']);
})();
Controller
(function() {
'use strict';
angular
.module('accountsApp')
.controller('accountsCtrl', accountsCtrl);
accountsCtrl.$inject = ['$log'];
function accountsCtrl($log, accountsDataSvc) {
/* jshint validthis:true */
var vm = this;
vm.title = 'Accounts';
vm.accounts = [];
vm.accountForm = null;
vm.account = { id: 0, name: '', description: '' }
activate();
function activate() {
return getAccounts(1).then(function() {
$log.info('Accounts loaded');
});
}
function getAccounts(id) {
return accountsDataSvc.getAccounts(id).then(function(data) { //error here
vm.accounts = data;
return vm.accounts;
});
}
}
})();
Service
(function () {
'use strict';
angular
.module('accountsApp')
.factory('accountsDataSvc', accountsDataSvc);
accountsDataSvc.$inject = ['$http', '$log'];
function accountsDataSvc($http, $log, $q) {
var uri = '***';
var service = {
getAccounts: accounts
};
return service;
//////////////////////
function accounts(userId) {
$log.info(uri + userId + ' called');
return $http.get(uri + userId)
.then(getAccountsComplete)
.catch(function (message) {
$log.error('XHR Failed for getAccounts ' + message);
});
function getAccountsComplete(data, status, headers, config) {
return data.data[0].data.results;
}
}
}
})();
When I run the application, I get the error TypeError: Cannot read property 'getAccounts' of undefined within the controller, but I can't see where I have gone wrong - any assistance would be much appreciated.
It looks like you forgot to inject accountsDataSvc into your controller
Try:
accountsCtrl.$inject = ['$log', 'accountsDataSvc'];
function configure($provide, $injector) {
$provide.provider("testservice", function () {
this.$get = function () {
this.property = 777;
};
});
var s = $injector.get("testservice");
The last line throws this error:
Unknown provider: testservice
Why so?
To access provide in config phase, we need to append 'Provider' to the name of the provider.
module.config(function ($provide, $injector) {
$provide.provider("testservice", function () {
this.$get = function () {
this.property = 777;
};
});
var s = $injector.get("testserviceProvider");
console.log(s)
});
i have a parser service which uses a fileReader service:
app.factory( 'parserService', [ '$q', 'fileReader', function ( $q, fileReader ) {
var parser = {};
parser.addASTtoFilesInTree = function ( fileTree ) {
var promises = [];
traverse(fileTree);
return $q.all(promises);
}
return parser;
}]);
and FileReader is:
app.factory( 'fileReader', [ '$q', function ($q) {
var fileReader = {};
fileReader.readFile = function( file ) {
var defer = $q.defer();
var reader = new FileReader();
reader.onload = function(e) {
defer.resolve(e.target.result);
};
reader.onerror = function(msg){
console.log(msg);
//add defer on error
};
reader.readAsBinaryString(file.ref);
return defer.promise;
};
return fileReader;
}]);
i am currently trying to create a test using karma - jasmine to test the addASTtoFilesInTree function in the parseService.
describe( "parser tests" , function() {
var parserService, $rootScope;
var mockFileReader = {
readFile: function( file ) {
var defer = $q.defer();
defer.resolve(file.ref.content);
console.log("in mockFileReader"); // this never gets called
return defer.promise;
}
};
var mockFileContent = "..."
var mockAST = { ... }
var itemOne = {...};
var parsedItemOne = { ... }
var mockFileTree = { ... };
beforeEach( function() {
//load the module
module('FYP');
//using mock service
module( function($provide) {
$provide.value = ('fileReader', mockFileReader);
});
//inject service for testing
inject( function( _$rootScope_, _parserService_) {
$rootScope = _$rootScope_;
parserService = _parserService_;
});
});
describe( "addASTtoFilesInTree", function() {
it('should add AST to all JS file', function() {
parserService.addASTtoFilesInTree(mockFileTree).then(function() {
console.log("in THEN"); //this never gets called
});
$rootScope.$digest();
expect(mockFileTree['root'].files['itemOne']).toEqual(parsedItemOne);//fails since it compares the two objects before promise is returned
});
});
});
The test is failing because its comparing the two objects before the promise returns. Am i missing something?
Try using a decorator:
//load the module
module('FYP');
//using mock service
module( function($provide) {
$provide.decorator('fileReader', function() {
return mockFileReader;
});
});
//inject service for testing
inject( function( _$rootScope_, _parserService_, _$q_ ) {
$rootScope = _$rootScope_;
parserService = _parserService_;
$q = _$q_;
});
or just a value service:
beforeEach(module('FYP'));
beforeEach(function () {
module( function($provide) {
$provide.value('fileReader', mockFileReader);
});
});
beforeEach(inject( function( _$rootScope_, _parserService_, _$q_) {
$rootScope = _$rootScope_;
parserService = _parserService_;
$q = _$q_;
}));