I want use unit test in angular, but the webapp that I working on it is created on its owe structure. for example :
(function() {
'use strict';
angular
.module('app', [
'ngAnimate',
'ui.load',
'ui.jp',
'oc.lazyLoad'
]);})();
And one of its controllers :
(function() {
'use strict';
angular
.module('app')
.controller('EditorCtrl', EditorCtrl);
function EditorCtrl($scope) {
var vm = $scope;
vm.options = {
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
]
};
}})();
And I have no idea how to use unit test to this app because my test cant find controller.
This is my controller and test :
(function () {
'use strict';
angular
.module('app')
.controller('DashboardCtrl', dashboard);
describe('test dashboard', function () {
beforeEach(module('DashboardCtrl'));
var $controller;
beforeEach(inject(function (_$controller_) {
$controller = _$controller_;
}));
describe('sum', function () {
it('1 + 1 should equal 2', function () {
var $scope = {};
var controller = $controller('DashboardCtrl', {$scope: $scope});
$scope.x = 1;
$scope.y = 2;
$scope.sum();
expect($scope.z).toBe(3);
});
it('z should default to zero', function () {
var $scope = {};
var controller = $controller('DashboardCtrl', {$scope: $scope});
expect($scope.z).toBe(0);
});
});
});
function dashboard($scope) {
$scope.name = 'Dashboard';
$scope.z = 0;
$scope.sum = function () {
$scope.z = $scope.x + $scope.y;
};
}
})();
And in karma test show me this error :
Error: [$injector:modulerr] Failed to instantiate module DashboardCtrl due to:
Error: [$injector:nomod] Module 'DashboardCtrl' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
That indicate that cant find "DashboardCtrl" controller.
the problem solved by add all modules in files options of karma.conf.js
the point is event lake of one of modules that are injected is main module that here is app stop your test, so addition to include your controller you need to add all module are mentioned.
When unit testing use $controller for getting a handle on a controller instance https://docs.angularjs.org/api/ng/service/$controller like var ctrlToTest = $controller('EditorCtrl')(newTestScope); To create a new test scope you can use var newTestScope = $rootScope.$new()
Related
Hi i am new to unit testing in angular. I am trying to add a simple test, but i keep getting an error saying that my angular controller is not registered. Below is my test case. I am not sure where i am going wrong?
'use strict';
/**
*
*/
describe('Controller',function() {
beforeEach(module('Module'));
var $controller;
beforeEach(inject(function(_$controller_) {
$controller = _$controller_;
}));
it("Should initialize AllValues to an empty array",function() {
var $scope = {
};
var testController= $controller(
'TestController', {
$scope : $scope
});
expect(testController.AllValues).toEqual(new Array());
})
});
below is my file structure in karma.conf.js
files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'App/**/*Test.js',
'App/**/*Module.js',
//'App/**/**.js',
]
May be you don't include 'TestController' refrence in 'specrunner.html'
I have setted up a test environment with Angular 1.6.6, ng-mock 1.6.6, Jasmine and Karma. But even with the easiest test I'm getting a [$injector:modulerr] when trying to inject the deloreanApp module
Failed to instantiate module deloreanApp due to: Error:
[$injector:nomod]
Theoretically there aren't tipo errors and Angular and ng-mock versions matches.
My files are:
app.js
(function () {
"use strict";
// initialize Angular
angular.module('deloreanApp', ['deloreanApp.controllers', 'deloreanApp.services']);
angular.module('deloreanApp.controllers', []);
angular.module('deloreanApp.services', []);
})();
controllers.js
(function () {
"use strict";
function deloreanController($scope){
$scope.sum = function(a,b){
return a + b;
}
}
angular.module('deloreanApp.controllers', []).controller('DeloreanController', ['$scope', deloreanController] );
})();
DeloreanController.test.js
describe('calculator', function () {
beforeEach(module('deloreanApp'));
var $controller;
beforeEach(inject(function (_$controller_) {
$controller = _$controller_;
}));
describe('sum', function () {
it('1 + 2 should equal 3', function () {
var result = 3;
expect(result).toBe(3);
});
});
});
And part of my karma.conf.js file:
// list of files / patterns to load in the browser
files: [
'lib/angular.min.js',
'lib/angular-mocks.js',
'js/app.js',
'js/controllers.js',
'tests/DeloreanController.test.js'
],
Try this,
(function () {
"use strict";
angular.module('deloreanApp.controllers', []);
angular.module('deloreanApp.services', []);
// initialize Angular
angular.module('deloreanApp', ['deloreanApp.controllers', 'deloreanApp.services']);
})();
I've seen this answered but none of the solutions are working for me. I'm getting an error Error: [ng:areq] Argument 'fn' is not a function, got undefined which is causing my test to fail. What's the correct way to inject a factory into a test spec that isn't a stubbed factory.
login module
angular.module('loginModule', ['ui.bootstrap', 'permission', 'ui.router', 'coreModule', 'utilsModule']);
login controller
(function(){
'use strict';
angular.module('loginModule')
.controller('loginController', login);
login.$inject = [
'$log',
'$uibModal',
'$rootScope',
'storageFactory',
'loginFactory',
'$state',
'RoleStore',
'PermissionStore',
'vsmsCoreFactory'
];
function login($log, $uibModal, $rootScope, storageFactory, loginFactory, $state, RoleStore, PermissionStore, vsmsCoreFactory) {
/* jshint validthis: true */
var vm = this;
vm.loginUser = loginUser;
vm.forgotPassword = forgotPassword;
vm.errorCode = null;
PermissionStore.clearStore();
vsmsCoreFactory.getHashFunction()
.then(function(response) {
if(response) {
storageFactory.setHashFunction(response); // unknown provider
}
});
function loginUser() {
...
login controller spec
describe('loginController', function() {
var $controller;
beforeEach(module('loginModule'));
beforeEach(inject(function(_$controller_){
$controller = _$controller_;
}));
describe('vm.loginUser', function() {
it('should be defined', function() {
var loginController = $controller('loginController');
expect(loginController.loginUser).toBeDefined();
});
});
});
unit test files
'use strict';
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var wiredep = require('wiredep');
var paths = gulp.paths;
function runTests (singleRun, done) {
var bowerDeps = wiredep({
directory: 'bower_components',
exclude: ['bootstrap-sass-official'],
dependencies: true,
devDependencies: true
});
var testFiles = bowerDeps.js.concat([
'./src/components/scripts/ui-bootstrap-custom-tpls-2.1.3.js',
'./src/app/index.js',
'./src/{app,components}/**/*.module.js',
'./src/{app,components}/**/*.factory.js',
'./src/{app,components}/**/*.controller.js',
'./src/{app,components}/**/*.spec.js'
]);
gulp.src(testFiles)
.pipe($.karma({
configFile: 'karma.conf.js',
action: (singleRun)? 'run': 'watch'
}))
.on('error', function (err) {
// Make sure failed tests cause gulp to exit non-zero
throw err;
});
}
gulp.task('test', function (done) { runTests(true /* singleRun */, done) });
gulp.task('test:auto', function (done) { runTests(false /* singleRun */, done) });
app
'use strict';
angular.module('fotaAdminPortal',
[
'ngAnimate',
'ngCookies',
'ngTouch',
'ngSanitize',
'ngResource',
'ui.bootstrap',
'ui.router',
'ui.router.stateHelper',
'pascalprecht.translate',
'utilsModule',
'loginModule',
...
])
log
Chrome 54.0.2840 (Mac OS X 10.11.6) loginController vm.loginUser should be defined FAILED
Error: [$injector:unpr] Unknown provider: storageFactoryProvider <- storageFactory <- loginController
The fotaAdminPortal module isn't loaded for the test so vsmsCoreFactory never gets registered.
Also there's no need to manually pass services into a controller as the injector will automatically do this when you create it. Passing services manually is useful when you need to pass something that isn't a globally registered service ie $scope or mock a service for a single controller instance.
Atm the mocks for the factories are just an undefined variable which will cause errors when the logic depending on them tries to call the methods that don't exist. You'll need to properly stub any methods on these mocks. But leaving those aside for the moment your test should be something like:
describe('loginController', function() {
var $controller;
beforeEach(module('fotaAdminPortal'));
beforeEach(inject(function(_$controller_){
$controller = _$controller_;
}));
describe('vm.loginUser', function() {
it('should be defined', function() {
var loginController = $controller('loginController');
expect(loginController.loginUser).toBeDefined();
});
});
});
If you want to load loginModule in isolation then you need to extract vsmsCoreFactory into another module and add that as a dependency:
angular.module('vsmsCore', [])
.factory('vsmsCoreFactory', function($http, env, $log, storageFactory) {
});
angular.module('loginModule', ['ui.bootstrap', 'permission', 'ui.router', 'vsmsCore']);
Then you can do beforeEach(module('loginModule')) instead
I am running my tests with karma and phantom, Also I'm using mocha and sinon and tests are getting failed with below error:
EditResourceCategoryDialogTest EditResourceCategoryDialogController "before each" hook: workFn
Error: [$injector:modulerr] http://errors.angularjs.org/1.4.9/$injector/modulerr?p0=resourceofferingsApp&p1=Error%3A%20%5B%24injector%3Amodulerr%5D%20
Sample code:
define(function (require) {
"use strict";
var assert = require('chai').assert;
var sinon = require('sinon');
var angular = require('angular');
var angularMocks = require('angular.mocks');
require('resourceofferings/app');
require('dialog path');
describe('EditResourceCategoryDialogTest', function () {
beforeEach(module('resourceofferingsApp'));
describe('EditResourceCategoryDialogController', function () {
var $scope, ctrl;
//you need to inject dependencies first
beforeEach(inject(function ($rootScope, $injector) {
$scope = $rootScope.$new();
}));
it('initialization test (create mode)', inject(function ($controller) {
ctrl = $controller("EditResourceCategoryDialogController", {
$scope: $scope,
$uibModalInstance: null,
options: {
isEditMode: false
}
});
assert.equal($scope.isEditMode, false);
}));
});
});
});
Its exactly getting failed here:
beforeEach(inject(function ($rootScope, $injector) {
$scope = $rootScope.$new();
}));
Please help me to fix this issue..
Thanks in advance.
Try this ...
describe('controllers', function(){
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new(); // this is what you missed out
controller = $controller('EditResourceCategoryDialogController', {
$scope: scope,
$uibModalInstance: null,
options: {
isEditMode: false
}
});
}));
});
Update: According to Angular ...
A common reason why the module fails to load is that you've forgotten
to include the file with the defined module or that the file couldn't
be loaded.
Are you sure all needed files are loaded?
My Jasmine unit test is as follows
describe('controllers', function () {
'use strict';
beforeEach(module('myapp.controllers'));
angular.mock.module('myapp.controllers', function ($provide) {
$provide.value('$localStorage', $localStorage);
});
it('should have a creationController', inject(function ($controller, _$rootScope_, localize) {
var scope = _$rootScope_.$new();
var localize = localize;
var myCtrl1 = $controller('creationController', {
$scope: scope,
localize: localize
});
expect(myCtrl1).toBeDefined();
}));
});
When I try to execute the test I'm getting the following error
Error: [$injector:unpr] http://errors.angularjs.org/1.2.20/$injector/unpr?p0=localizeProvider%20%3C-%20localize
There is a dependency called as "localize" being used in the controller. However I'm unable to inject that in to this unit test.
Any idea how I can solve this problem ?
injector look for _componenrToBeInjected_ for injection . If you have a service name localized (Are you sure you have one ?) then for injection use
_ localize_ so your it block should look like this .
it('should have a creationController', inject(function ($controller, _$rootScope_, _localize_) {
var scope = _$rootScope_.$new();
var localize = _localize_;
var myCtrl1 = $controller('creationController', {
$scope: scope,
localize: localize
});
expect(myCtrl1).toBeDefined();
}));