I am having a lot of trouble getting dependencies provided properly for an AngularJS service.
I see a number of other posts with similar errors here on StackOverflow but none of them seem to resolve the issue.
Here is the app code:
cm.modules.app = angular.module('myApp', ['ngRoute', 'ngAnimate']);
myServiceName = function($http) {
// do stuff
};
myServiceName.prototype.value = 1;
cm.modules.app.service('defaultAlertFactoryA', myServiceName);
Here is the test code:
describe('test alertFactoryA', function() {
var $provide;
var mAlertFactoryA;
beforeEach(module(cm.modules.app));
beforeEach(angular.mock.module(function(_$provide_) {
$provide = _$provide_;
}));
beforeEach(function() {
inject(function($injector) {
mAlertFactoryA = $injector.get('defaultAlertFactoryA');
});
});
it('should work', function() {
expect(true).toBe(true);
});
});
Here is the error:
Error: [$injector:unpr] Unknown provider: defaultAlertFactoryAProvider
<- defaultAlertFactoryA
http://errors.angularjs.org/1.2.0-rc.2/$injector/unpr?p0=defaultAlertFactoryAProvider%20%3C-%20defaultAlertFactoryA
Question: How do I fix this so the test passes?
In order to bootstrap your module you need to provide its name
beforeEach(module('myApp'));
Demo
The following is what I used to get it working (finally)
beforeEach(function() {
module(cm.modules.app.name);
module(function($provide) {
$provide.service('defaultAlertFactoryA', myServiceName);
});
inject(function($injector) {
defaultAlertFactory = $injector.get('defaultAlertFactoryA');
});
});
Sounds like you need to include the service files in your karma.conf.js file
files: [
'app/bower_components/angular/angular.js',
'app/bower_components/angular-mocks/angular-mocks.js',
'app/bower_components/angular-ui-router/release/angular-ui-router.js',
'app/app.js',
'app/controllers/*.js',
'app/services/*.js',
'tests/**/*.js'
],
If the are not included here they can't be accessed in the unit tests
Related
I have a module
export default angular.module('pfui.user', [])
.controller('ModifyUserController', ModifyUserController)
that has a controller
export default class ModifyUserController{
userid:string;
...
}
I'm trying to create a unit test that can test some methods in the controller that calls services to do some operation. This is my Karma script -
describe('ModifyUserControllerTester', function () {
var $controller;
beforeEach(angular.mock.module('ui.router'));
beforeEach(angular.mock.module('pfui.user'));
beforeEach(inject(function (_$controller_) {
$controller = _$controller_;
}));
describe('Test', function () {
it('test accessing controller', function () {
let $scope = {};
var controller = $controller('ModifyUserController', {
$scope: $scope
});
expect($scope['userid']).toBe(undefined);
});
});
});
When I run the test, I get an error
Error: [$injector:unpr] Unknown provider: UsersProvider <- Users <- ModifyUserController
Initially I was getting an error that $stateProvider was missing. So I added
beforeEach(angular.mock.module('ui.router'));
and that error went away.
This is my first attempt in writing a Karma test. I'm not sure what I am missing. Why is Karma looking for a Provider when I don't have one in the module? Any help is greatly appreciated.
Your question doesn't show any dependency injections to the ModifyUserController but going by the error you have posted it looks like you haven't provided the 'Users' Service to the controller.
describe('ModifyUserControllerTester', function () {
var $controller;
var mockUsers;
beforeEach(angular.mock.module('ui.router'));
beforeEach(angular.mock.module('pfui.user'));
beforeEach(inject(function (_$controller_) {
$controller = _$controller_;
}));
describe('Test', function () {
it('test accessing controller', function () {
//----define your mock dependency here---//
let mockUsers = jasmine.createSpyObj('mockUsers', ['user_method1',
'user_method2',...]);
let $scope = {};
var controller = $controller('ModifyUserController', {
$scope: $scope,
Users: mockUsers
});
expect($scope['userid']).toBe(undefined);
});
});
});
PS. Since its best practice for unit tests to be conducted in isolation, you should also consider providing a mock state provider vs importing the actual ui.router module
I have the following service with a constant:
angular.module('app',[]).constant('alertType',{
success:1,
error:0
})
.factory("dataService",dataService);
dataService.$inject = ['$timeout', 'alertType']
function dataService($timeout, alertType) {
return {
//some code related to the service
}
}
Here is the test case for the service to check if it is registered or not
describe('Testing "dataService" service', function() {
var _dataService;
beforeEach(function() {
module('app');
inject(function(dataService) {
_dataService = dataService;
});
});
it('Should be registered', function() {
expect(_dataService).toBeDefined();
});
});
For some reason it doesn't work. I get a very long error that looks something like this:
Error: [$injector:unpr] Unknown provider: dataServiceProvider <- dataService http://errors.angularjs.org/1.3.0/$injector/unpr?p0=dataServiceProvider%20%3C-%20dataService
Am I doing it right or is there anything wrong with this?
Try mocking your provider at the top of your describe block like so:
beforeEach(module($provide => {
$provide.constant('alertType',{
success: 1,
error: 0
});
}));
For more details please refer to this answer: Unknown Provider when unit testing filter
I have the following module:
angular.module('config', []).constant('myconstant', somevalue);
I would like to unit test this so I created:
describe('Constants', function () {
var config;
beforeEach( inject(function (_config_) {
module('config');
config =_config_;
}));
it('should return settings',function(){
expect(config.constant('myConstant')).toEqual('somevalue');
});
});
Getting an error now:
Error: [$injector:unpr] Unknown provider: configProvider <- config
How can I fix this?
You should be injecting your constant like any other service and not your module. This works for me:
angular.module('config', []).constant('myconstant', 'somevalue');
describe('Constants', function () {
var myconstant;
beforeEach(module('config'));
beforeEach( inject(function (_myconstant_) {
myconstant =_myconstant_;
}));
it('should return settings',function(){
expect(myconstant).toEqual('somevalue');
});
});
I've got this in app.js:
angular.module('App',[]).config(['TranslationProvider', function (TranslationProvider) {
//codes...
}]);
And this service in another file:
angular.module('App')
.provider('Translation', function() {
var translations = {foo:"bar"}
this.$get = function(){
return translations;
};
});
No 404 error with the service js file, but when angular injector try to instantiate it gives me this error:
Uncaught Error: [$injector:modulerr] Failed to instantiate module App due to:
Error: [$injector:unpr] Unknown provider: TranslationProvider
I've followed the angjs documentation https://docs.angularjs.org/guide/providers
It seems to be a bug in Angular 1.2.x. The order of the calls matter. When you call provide before config it works. It also works with Angular 1.3.x regardless of the order.
You are almost there.
First the config:
angular.module('App')
.config(["TranslationProvider", function(theProvider) {
console.log("in config" + theProvider)
theProvider.setName("some name");
}]);
The error you were having was due to you using the constructor function as an argument.
Now your provider:
angular.module('App')
.provider('Translation', function TranslationProvider() {
var translations = {foo:"bar", name:""};
var dynamicName;
this.setName = function(configName) {
dynamicName = configName;
};
this.$get = function(){
translations.name = dynamicName;
return translations;
};
});
Also note that an anonymous function (i.e. .provider('Translation', function () {) could also have been used and the code would have worked just as well.
Using it all in a controller:
angular.module('App')
.controller('MyController', [
'$scope',
'Translation',
function ($scope,
translationProvider) {
$scope.modal = {};
$scope.projects = [];
console.log(translationProvider)
$scope.foo = translationProvider;
}]);
I'm having trouble getting my tests to run due to dependencies not beeing injected correctly.
The error I'm getting is defined in the title. I've included the actual test code, the app.js & index.html file from my solution.
The problem lies with the deferred bootstrap which I'm not fimiliar with as it was included by one of my colleagues. If I remove the "app.config(function (STARTUP_CONFIG..." from the app.js file then the test runs fine
How can I correctly inject the STARTUP_CONFIG in my test?
test code
..
..
describe("test description...", function () {
var app;
var mockupDataFactory;
beforeEach(module('Konstrukt'));
beforeEach(inject(function (STARTUP_CONFIG,BUDGETS,APPLICATIONS) {
//failed attempt to inject STARTUP_CONFIG
}));
beforeEach(function () {
app = angular.module("Konstrukt");
});
beforeEach(function () {
mockupDataFactory = konstruktMockupData.getInstance();
});
it('should be accessible in app module', function () {
expect(app.pivotTableService).toNotBe(null); //this test runs fine
});
it('test decr...', inject(function ( pivotTableService) {
... //Fails here
..
..
app.js
..
..
angular.module('Konstrukt', ['ngGrid', 'ngSanitize', 'ngRoute','pasvaz.bindonce', 'ngAnimate', 'nvd3ChartDirectives', 'ui.select', 'ngProgress', 'ui.grid', 'ui.grid.edit','ui.grid.selection', 'ui.grid.cellNav', 'ui.grid.pinning', 'ui.grid.resizeColumns']);
var app = angular.module('Konstrukt');
app.config(function (STARTUP_CONFIG, BUDGETS, APPLICATIONS) {
var STARTUP_CONFIG = STARTUP_CONFIG;
var BUDGETS = BUDGETS;
var APPLICATIONS = APPLICATIONS;
});
..
..
index.html
..
..
<script>
setTimeout(function(){
window.deferredBootstrapper.bootstrap({
element: window.document.body,
module: 'Konstrukt',
resolve: {
STARTUP_CONFIG: ['$http', function ($http) {
return $http.get('/scripts/_JSON/activeBudgets.JSON');
}],
BUDGETS: ['$http', function ($http) {
return $http.get('/scripts/_JSON/activeBudgets.JSON');
}],
APPLICATIONS: ['$http', function ($http) {
return $http.get('/scripts/_JSON/applications.JSON');
}]
}
})
} , 1500);
</script>
The deferredBootstrapper will not run in your unit tests, which means the constants it normally adds to your module won't be available.
You can add a global beforeEach that provides mocked versions of them:
beforeEach(function () {
module(function ($provide) {
$provide.constant('STARTUP_CONFIG', { something: 'something' });
$provide.constant('BUDGETS', { something: 'something' });
$provide.constant('APPLICATIONS', { something: 'something' });
});
});