Error in Karma/Jasmine Unit test - angularjs

This is my AngularJS code:
angular.module('myapp', [])
.controller('MainCtrl', function($scope, $http, $rootScope, $routeParams) {
$scope.name = "Girish";
$scope.sayHello = function() {
$scope.greeting = "Hello " + $scope.name;
};
$scope.commonUrl = "/";
$rootScope.$watch('eng', function() {
$scope.currentLang = $rootScope.CURRENT_LANGUAGE;
});
$scope.homePageFirstSlider = function() {
$scope.anun = "Nar";
$http({
method: 'GET',
url: "/" + "eng" + '/api/getslideritems/main'
}).then(function successCallback(response) {
$scope.Data = response.data;
$scope.loadCss('mainCarousel');
},
function errorCallback(response) {});
};
});
This is a test file:
'use strict';
describe('myapp', function() {
beforeEach(module('myapp'));
var $controller;
beforeEach(inject(function(_$controller_) {
// The injector unwraps the underscores (_) from around the parameter names when matching
$controller = _$controller_;
}));
describe('$scope.sayHello', function() {
it('same tests', function() {
var $scope = {};
var controller = $controller('MainCtrl', { $scope: $scope });
$scope.name = 'Girish';
$scope.sayHello();
expect($scope.greeting).toEqual('Hello Girish');
});
});
});
After I run karma.conf.js file I have this error:
PhantomJS 2.1.1 (Linux 0.0.0) myapp $scope.sayHello same tests FAILED
***Error: [$injector:unpr] Unknown provider: $routeParamsProvider <- $routeParams <- MainCtrl***
http://errors.angularjs.org/1.5.0/$injector/unpr?p0=%24routeParamsProvider%20%3C-%20%24routeParams%20%3C-%20MainCtrl in /var/www/html/famboxv2/public/bower_components/angular/angular.js (line 4397)
loaded#http://localhost:9882/context.js:151:17
PhantomJS 2.1.1 (Linux 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.025 secs / 0.004 secs)
Chromium 45.0.2454 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.008 secs / 0.005 secs)
How can I solve this error?
Unknown provider: $routeParamsProvider <- $routeParams <- MainCtrl

$routeParams service is a part of ngRoute module. So you'll have to include it as a dependency on your module.
Here's how:
angular.module('myapp', ['ngRoute'])
Also you should be mocking the controller in the first beforeEach block instead of mocking it inside a specific test, so that it could be reusable in all your tests.
And your tests will still be failing because you've inject an empty object for $scope instead of creating a new scope using the $rootScope's $new function. So you should be doing the following changes to make them pass:
describe('myapp', function() {
beforeEach(module('myapp'));
//Replace this
beforeEach(inject(function($controller, _$rootScope_){
//With this
// beforeEach(inject(function($controller, _$rootScope_, _$routeParams_, _$http_){
//Uncomment the following comments if needed for writing tests for the $watch function.
// $rootScope = _$rootScope_;
$scope = _$rootScope_.$new();
// $http = _$http_;
// $routeParams = _$routeParams_;
controller = $controller('MainCtrl', {
$scope: $scope,
// $http: $http,
// $rootScope: $rootScope,
// $routeParams: $routeParams
});
}));
describe('$scope.sayHello', function() {
it('same tests', function() {
$scope.name = 'Girish';
$scope.sayHello();
expect($scope.greeting).toEqual('Hello Girish');
});
});
});

Related

Jasmine unit-test case failing on the injection of the dependencies

These are my controllers and services that I am trying to cover using Jasmine testing.
home.controller.js
var home = angular.module('home',[])
home.controller('home.controller', ['$scope','$location','homeService','localStorageService',function ($scope,$location,homeService,localStorageService) {
homeService.directories(1001).then(function mySucces(_data) {
$scope.dataHome = _data;
}, function myError(response) {
alert("error");
});
$scope.func = function(fileData) {
localStorageService.set('fileId',fileData.id);
console.log(fileData.id);
$location.path("fileview");
};
}]);
home.service.js
var homeService = angular.module('homeService',[]);
homeService.factory('homeService',['$http', '$q', '$log','config', function ($http, $q, $log,config) {
var serviceAPI = {};
serviceAPI.directories = function (folderId) {
var deferred = $q.defer();
$http.get(config.service + "/filevault-service/folders").then(function mySucces(response) {
deferred.resolve(response.data.data);
}, function myError(response) {
deferred.resolve(response.status);
});
return deferred.promise;
}
return serviceAPI;
}]);
Here goes my test case:
describe('equality', function() {
var rootScope, homeService, scope, homeController, httpBackend, location, localStorageService;
beforeEach(function(){
module('fileVaultApp');
inject(function($controller, $httpBackend, $rootScope, $location, homeService, localStorageService){
rootScope = $rootScope;
scope = $rootScope.$new();
httpBackend = $httpBackend;
homeService = homeService;
location = $location;
localStorageService = localStorageService;
homeController = $controller('home.controller', { $scope: scope });
spyOn($location, 'path');
});
});
console.log("hello");
it('check the home controller', function() {
expect(1).toBe(1);
});
});
The thing is that when I am removing the "inject" snippet, the test runs good. As soon as it is injected, the problem arises.
The error has been given below:
PhantomJS 2.1.1 (Windows 7 0.0.0) equality check the home controller FAILED
C:/FileVault/file-vault/filevault-ui/static/scripts/lib-min.js:4641:53
forEach#C:/FileVault/file-vault/filevault-ui/static/scripts/lib-min.js:321:24
loadModules#C:/FileVault/file-vault/filevault-ui/static/scripts/lib-min.js:4601:12
createInjector#C:/FileVault/file-vault/filevault-ui/static/scripts/lib-min.js:4523:30
workFn#C:/FileVault/file-vault/filevault-ui/static/scripts/lib-min.js:50216:60
inject#C:/FileVault/file-vault/filevault-ui/static/scripts/lib-min.js:50196:46
C:/FileVault/file-vault/filevault-ui/tests/test_jasmine_spec.js:7:12
PhantomJS 2.1.1 (Windows 7 0.0.0): Executed 1 of 1 (1 FAILED) (0 secs / 0.012 secs)
You should inject _homeService_, and _localStorageService_;
inject(function($controller, $httpBackend, $rootScope, $location, _homeService_, _localStorageService_){
Also you should inject all the dependencies of the controller when instantiating it.
describe('equality', function() {
var rootScope, homeService, scope, homeController, httpBackend, location, localStorageService;
beforeEach(function(){
module('fileVaultApp');
inject(function($controller, $httpBackend, $rootScope, $location, _homeService_, _localStorageService_){
rootScope = $rootScope;
scope = $rootScope.$new();
httpBackend = $httpBackend;
homeService = _homeService_;
location = $location;
localStorageService = _localStorageService_;
homeController = $controller('home.controller', { $scope: scope, $location:location, homeService: homeService, localStorageService: localStorageService});
spyOn($location, 'path');
});
});
console.log("hello");
it('check the home controller', function() {
expect(1).toBe(1);
});
});

Error: Unexpected request: GET /api/users/me meanstack jasmine testing

Please help my http request keeps failing and i have tried different methods from Internet
test.js
{
describe('EcdreportController', function(){
beforeEach(function() {
module('mean');
module('mean.ecdreport');
});
// Initialize the controller and a mock scope
var EcdreportController,
$scope,
$httpBackend,
$stateParams,
$location;
beforeEach(inject(function($controller, $rootScope, _$location_, _$stateParams_, _$httpBackend_,$http) {
$scope = $rootScope.$new();
EcdreportController = $controller('EcdreportController', {
$scope: $scope,
$http : $http
});
$stateParams = _$stateParams_;
$httpBackend = _$httpBackend_;
$location = _$location_;
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('$scope.getdatamodel',function($http){
// test expected GET request
$httpBackend.expectGET('/api/v1/getdatamodel').respond(200);
//expect($httpBackend.flush).not.toThrow();
$httpBackend.flush();
$scope.getDataModel()
expect($scope.datamodel).toEqual(data)
});
})
}
controllers.js
$scope.getDataModel = function() {
$http({url:'/api/v1/getdatamodel', method:"GET"})
.success(function(data) {
console.log('Datamodel successful');
$scope.datamodel = data[0];
console.log('datamodel', data);
})
.error(function(error) {
$scope.datamodel =[];
});
}
// console.log("Trying to get datamodel");
$scope.getDataModel();`
terminal results
PhantomJS 2.1.1 (Linux 0.0.0) EcdreportController $scope.getdatamodel FAILED
Error: Unexpected request: GET /api/users/me
Expected GET /api/v1/getdatamodel in bower_components/angular-mocks/angular-mocks.js (line 1412)
$httpBackend#bower_components/angular-mocks/angular-mocks.js:1412:90
n#bower_components/angular/angular.min.js:98:461
bower_components/angular/angular.min.js:95:490
bower_components/angular/angular.min.js:130:511
$eval#bower_components/angular/angular.min.js:145:107
$digest#bower_components/angular/angular.min.js:142:178
flush#bower_components/angular-mocks/angular-mocks.js:1791:45
packages/custom/ecdreport/public/tests/ecdreport.tests.js:71:21
Error: [$rootScope:inprog] http://errors.angularjs.org/1.5.7/$rootScope/inprog?p0=%24digest in bower_components/angular/angular.min.js (line 137)
n#bower_components/angular/angular.min.js:137:402
$digest#bower_components/angular/angular.min.js:142:31
verifyNoOutstandingExpectation#bower_components/angular-mocks/angular-mocks.js:1823:45
packages/custom/ecdreport/public/tests/ecdreport.tests.js:63:46
PhantomJS 2.1.1 (Linux 0.0.0): Executed 3 of 3 (1 FAILED) (0.056 secs / 0.074 secs)

AngularJS Controller Unit Testing

I new in AngularJS and try Unit Testing.I am using Karma and Jasmine. I created the first test for my controller but its not working and I don't know why karma throughs an error.
So please help me out this.
BasicTabCtrl.js
// Basic Tab Controller
myApp.controller('BasicTabCrtl', ['$scope', '$modal', 'BasicTabService', function ($scope, $modal, BasicTabService) {
console.log("BAsic tab crtl");
$scope.name = 'testing';
$scope.tab1 = "BASIC";
$scope.tab2 = "ADVANCE";
$scope.tab3 = "FORM";
$scope.user = {};
// get user from service
$scope.Tablelist = BasicTabService.getUser();
// delete user
$scope.deleteUser = function (obj) {
console.log("OBJ => " + JSON.stringify(obj));
if (obj != -1) {
$scope.Tablelist.splice(obj, 1);
}
}
}]);
Here is my test case
example.js
describe('myApp',function(){
var scope,controller;
beforeEach(function(){
module('myApp');
});
describe('BasicTabCrtl',function(){
beforeEach(inject(function($rootScope,$controller){
scope = $rootScope.$new();
controller=$controller('BasicTabCrtl',{
'$scope':scope
});
console.log("d");
}));
it('set the name',function(){
expect(scope.name).toBe('testing');
});
});
});
Error
26 05 2016 20:47:50.890:INFO [watcher]: Changed file "/home/rahul/Documents/django_project/myfirstsite/test/example.js".
Firefox 46.0.0 (Ubuntu 0.0.0) myApp BasicTabCrtl set the tab1 name FAILED
minErr/<#/home/rahul/Documents/django_project/myfirstsite/static/js/angular.js:68:12
loadModules/<#/home/rahul/Documents/django_project/myfirstsite/static/js/angular.js:4587:15
forEach#/home/rahul/Documents/django_project/myfirstsite/static/js/angular.js:322:11
loadModules#/home/rahul/Documents/django_project/myfirstsite/static/js/angular.js:4548:5
createInjector#/home/rahul/Documents/django_project/myfirstsite/static/js/angular.js:4470:19
workFn#/home/rahul/Documents/django_project/myfirstsite/static/js/angular-mocks.js:2954:44
TypeError: scope is undefined in /home/rahul/Documents/django_project/myfirstsite/test/example.js (line 19)
#/home/rahul/Documents/django_project/myfirstsite/test/example.js:19:3
Firefox 46.0.0 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.023 secs / 0.018 secs)
I believe the injection isn't working because of missing _ around angular methods
describe('myApp',function(){
var scope,controller;
beforeEach(function(){
module('myApp');
});
describe('BasicTabCrtl',function(){
beforeEach(inject(function(_$rootScope_, _$controller_){
scope = _$rootScope_.$new();
controller = $controller('BasicTabCrtl',{
'$scope':scope
});
console.log("d");
}));
it('set the name',function(){
expect(scope.name).toBe('testing');
});
});
});
Try this :
Create controller instance :
callController = function () {
return $controller('BasicTabCrtl', {
$scope: scope,
$routeParams: routeParams
});
};
Then test that it's defined or not . If this test pass then you can continue with unit test.
describe('null test', function () {
it('controller should be defined', function () {
ctrl = callController();
expect(ctrl).to.not.be.undefined;
});
});
The problem with your code is you are not injecting all of the dependencies when you instantiate your controller. Try this...
beforeEach(inject(['$scope', '$modal', 'BasicTabService', '$controller', '$rootScope', function ($scope, $modal, BasicTabService, $controller, $rootScope){
scope = $rootScope.$new();
controller=$controller('BasicTabCrtl',{
'$scope':$scope,
'$modal':$modal,
'BasicTabService': BasicTabService
});
console.log("d");
}));
Try my answer from Jasmine, Karma, Angular how to write test on my Angular app?. I describe how to test controllers and services and directives.

How to correctly inject a factory using Jasmine / karma and test it?

This is my factory / base.js:
angular.module("BaseApp", [])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}])
.config(['$locationProvider', function($locationProvider){
$locationProvider.html5Mode(true);
}])
.factory("BaseService", ["$http", "$window", function($http, $window) {
And this is my test_base.js:
describe('Factory: BaseService', function() {
var fctry, mockBackend;
beforeEach(function() {
module('BaseApp');
inject(function($factory, $httpBackend) {
mockBackend = $httpBackend;
fctry = $factory('BaseService', {});
});
});
it('logout() should POST to /logout', function() {
// I want to test if the logout(cb) function posts to /logout and, on success, redirect to '/'
// but on failure, calls accessErrors and the cb.
});
});
This is my karma config file:
files: [
'../angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'../base.js',
'tests/test_base.js',
],
When I do karma start and run the tests, I get this error / fail:
Chromium 48.0.2564 (Ubuntu 0.0.0) Factory: BaseService logout() should POST to /logout FAILED
Error: [$injector:unpr] Unknown provider: $factoryProvider <- $factory
http://errors.angularjs.org/1.3.15/$injector/unpr?p0=%24factoryProvider%20%3C-%20%24factory
...
Chromium 48.0.2564 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) (0 secs / 0.053 secChromium 48.0.2564 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.114 secs / 0.053 secs)
How come it is failing already and how come it is saying that $factoryProvider is an unknown provider?
It thinks you're trying inject factory, which is a function, not a provider, so that won't work.
You're also missing out on the underscore trick
Try changing this:
var fctry, mockBackend;
beforeEach(function() {
module('BaseApp');
inject(function($factory, $httpBackend) {
mockBackend = $httpBackend;
fctry = $factory('BaseService', {});
});
});
To this:
var BaseService, $httpBackend;
beforeEach(function() {
module('BaseApp');
inject(function(_BaseService_, _$httpBackend_) {
$httpBackend = _$httpBackend_;
BaseService = _BaseService_;
});
});

AngularJS mocking promise TypeError: 'undefined' is not an object (evaluating 'queryDeferred.resolve')

I'm trying to put some tests on a controller using ressources/promises. I had followed the article Mocking $resource and promises in AngularJS unit tests.
However I can't get a simple case to work as the queryDeferred object is undefined.
Error
PhantomJS 1.9.8 (Linux) OrdersModule API.Orders.query should query the API.Orders FAILED
TypeError: 'undefined' is not an object (evaluating 'queryDeferred.resolve')
at /mnt/data/projects/tcs_economat/frontend/static_src/test/unit/orderSpec.js:52
PhantomJS 1.9.8 (Linux): Executed 25 of 25 (1 FAILED) (0.235 secs / 0.223 secs)
Controller
"use strict";
angular.module('OrdersModule', ['services'])
.controller('OrdersControllers', ['$scope', 'API', function ($scope, API) {
$scope.orders = [];
API.Order.query().$promise.then(function (data) {
console.log(data);
});
}]
);
Test
"use strict";
describe('OrdersModule', function () {
var $q,
$rootScope,
$scope,
mockOrdersApiService,
queryDeferred,
mockOrdersResponse = [
{status: 'DRAFT'},
{status: 'DRAFT'}
];
beforeEach(module('tcsStoreApp'));
beforeEach(inject(function (_$q_, _$rootScope_) {
$q = _$q_;
$rootScope = _$rootScope_;
}));
beforeEach(inject(function ($controller) {
$scope = $rootScope.$new();
mockOrdersApiService = {
query: function () {
queryDeferred = $q.defer();
return {$promise: queryDeferred.promise};
}
};
spyOn(mockOrdersApiService, 'query').andCallThrough();
$controller('OrdersControllers', {
'$scope': $scope,
'API.Orders': mockOrdersApiService
});
}));
describe('API.Orders.query', function () {
beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) {
var $httpBackend = _$httpBackend_;
queryDeferred.resolve(mockOrdersResponse);
$rootScope.$apply();
$httpBackend.expectGET('/static/js/tcs.fr.json').respond({});
}));
it('should query the API.Orders', function () {
expect(mockOrdersApiService.query).toHaveBeenCalled();
});
});
});
Question
Is the mockOrdersApiService correctly declared?
Why is the queryDeferred.resolve undefined?

Resources