Module is not available in angularjs + Jasmine Unit testing - angularjs

Module is defined as
var $manage = angular.module('manage', [....]);
Controller is defined as
$manage.line.events.controller('eventsController', [..., function(...){
$scope.page = "events";
}]);
My simple unit test case is
describe('Module: manage', function() {
beforeEach(module('manage'));
var scope, ctrl, rootScope;
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
ctrl = $controller('eventsController', {
$scope: scope
});
}));
it("test page", function () {
expect(scope.page).toEqual('events');
});
});
Here, i am getting a error like
Failed to instantiate module ampleManage due to.... manage is not available.
I have integrated angular-mocks.js also. Tried so many possibilities but not working for me.
Basic need is .
Need to access controller/scope in test case.

Related

Unit testing angular.js service (node.js server) in controller

I'm new to the unit testing in the client side. My application uses the express.js, angularjs-ui-router and node.js. Currently i start writing the unit test cases for the application. I'm using Karma, Mocha, Chai, Sinon for unit testing.
My router config look like below:
$stateProvider
.state('drive', {
url: '/drive',
templateUrl: 'drive.jade',
controller: 'driveCtrl',
});
Controller:
angular.module('mApp').controller('driveCtrl', ['$scope', 'driveService',
function($scope, driveService) {
var driveInfo = driveService.get({}, function() {});
driveInfo.$promise.then(function(rs) {
var drivers = [];
//Logical operation
$scope.drivers = drivers;
});
}]);
Factory Resource:
mApp.factory('driveService', ['$resource', function($resource) {
return $resource('/drive/id/:id/', {id:'#id'});
}]);
The driveService is a factory which insides uses a angular.js $resources. I tried variety of options but nothings seems to be working (using the $httpbackend, $q). Can you help me out to write the way to test the controller by mocking the driveService.
Here's my unit test code:
var expect = require('chai').expect;
var sinon = require('sinon');
describe('Drive Service initialisation', function() {
var scope, controller, state, $q, mockDriveService, driveServiceResponse = [{name:'james', type: 'heavy'}], queryDeferred;
beforeEach(angular.mock.module('mApp'));
angular.mock.module(function($provide){
$provide.value('driveService', mockDriveService);
});
describe(' drive service called', function() {
beforeEach(inject(function($controller, $rootScope, $state, _$q_, driveService) {
$q = _$q_;
scope = $rootScope.$new();
mockDriveService = {
get:function(){
queryDeferred = $q.defer();
queryDeferred.resolve(driveServiceResponse);
return {$promise: queryDeferred.promise};
}
};
controller = $controller('driveCtrl', { $scope: scope, driveService:driveService});
sinon.stub(mockDriveService, 'get');
scope.$apply();
}));
it('expect filter to be empty', function () {
expect(scope.drivers).to.not.be.empty;
});
});
});
The error what i'm getting is:
Error: Unexpected request: GET /driveService/id
No more request expected
at $httpBackend (node_modules/angular-mocks/angular-mocks.js:1210:9)
at sendReq (public/javascripts/lib/angular/angular.js:10333:9)
at serverRequest (public/javascripts/lib/angular/angular.js:10045:16)
at processQueue (public/javascripts/lib/angular/angular.js:14567:28)
at public/javascripts/lib/angular/angular.js:14583:27
at Scope.$eval (public/javascripts/lib/angular/angular.js:15846:28)
at Scope.$digest (public/javascripts/lib/angular/angular.js:15657:31)
at Scope.$apply (public/javascripts/lib/angular/angular.js:15951:24)
at Context.<anonymous> (C:/Users/por/AppData/Local/Temp/b0475694b46e0d60262621ad126ce46c.browserify:63:9)
at Object.invoke (public/javascripts/lib/angular/angular.js:4450:17)
Error: Declaration Location
at window.inject.angular.mock.inject (node_modules/angular-mocks/angular-mocks.js:2375:25)
You're defining a mocked service but still providing unmocked driveService for controller (this has been already done by default).
The fact that driveService.get is stubbed after the controller was instantiated and the method was called, doesn't help the case.
It should be something like
mockDriveService = {
get: sinon.stub().returns({$promise: $q.resolve(driveServiceResponse)})
};
controller = $controller('driveCtrl', { $scope: scope, driveService:mockDriveService});
scope.$apply();
The app should have test-friendly design to be tested efficiently. Considering that router is loaded in top-level module and its configuration is defined there too, app units that are supposed to be tested should be defined in child modules, so they could be tested in isolation.
The app may be refactored as
angular.module('mApp', ['ui.router', 'mApp.drive']);
...
angular.module('mApp.drive', [])
.controller('driveCtrl', ...)
.factory('driveService', ...);
And its units may be tested like
beforeEach(angular.mock.module('mApp.drive'));
...

Error: $injector:unpr AngularJS Testing mocking object instances

I keep running into problems at the minute when i'm testing my AngularJS applications, I try and inject all dependencies however it doesn't seem to be working, any help is greatly appreciated :)
It's quite a large application and i'm trying to break things down as much as possible and test them, however we have a factory called firebaseUser which is, as you can guess a firebaseUser. We also have an instance of this known as userInstance so I'm getting errors whenever I try and mock userInstance.
describe('Dashboard Start Controller', function () {
var scope, ctrl;
beforeEach(function () {
MockFirebase.override();
module('noodleApp.start');
module('noodleApp.noodleFactory');
module('noodleApp.firebaseUser');
module('noodleApp.start');
});
beforeEach(inject(function($rootScope, $controller, $injector) {
scope = $rootScope.$new();
ctrl = $controller('StartController', {$scope: scope});
}));
afterEach(function () {
scope.$destroy();
});
it('should be available', function() {
expect(ctrl).toBeDefined();
});
it('should init with filter being set to all', function() {
expect(scope.filterOn).toBe('all');
});
});
Whenever I run this test I get the following error: Unknown provider: userInstanceProvider <- userInstance <- StartController
$controller is a call to $inject but treated as a service. What happens is you are instantiating the controller but because $inject is used, and you are not passing userInstance, it looks for a provider which isn't found. You need to make sure to pass the service/factory/resolve to your $controller method. By mocking it out and passing it to the controller, you can isolate what you expect to happen and only test the controller in this unit test.
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
userInstanceMock = {
// mock out all methods here
foo: sinon.stub()
}
ctrl = $controller('StartController', {
$scope: scope,
userInstace: userInstaceMock
});
}));

Unit testing Angular JS controllers

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();
}));

Unit-testing with Karma-Jasmine

I'm using angularJS and i understand how to test my $scope objects with karma-jasmine but i'm having difficulties testing regular functions and variables inside my controller file
//controller.js
angular.module('myApp').controller('mainCtrl', function ($scope) {
$scope.name = "bob";
var aNumber = 34;
function myFunction(string){
return string;
}
});
what i would like to do is to test to see if expect(aNumber).toBe(34);
// test.js
describe('Controller: mainCtrl', function () {
// load the controller's module
beforeEach(module('myApp'));
var mainCtrl,
scope;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
mainCtrl = $controller('mainCtrl', {
$scope: scope
});
}));
// understand this
it('should expect scope.name to be bob', function(){
expect(scope.name).toBe('bob');
});
// having difficulties testing this
it('should expect aNumber to be 34', function(){
expect(aNumber).toBe(34);
});
// having difficulties testing this
it('should to return a string', function(){
var mystring = myFunction('this is a string');
expect(mystring).toBe('this is a string');
});
});
It looks you are trying to test private variables declared in angular controller. The variables which are not exposed through the $scope cannot be tested, as they are hidden, and are visible only in a function scope inside the controller. More on private members and information hiding in javascript you can find here
The way how you should approach private fields in tests is by testing them through exposed api. If the variable is not used in any exposed publicly method it means that it's not used so it doesn't make sense to keep it and test it.

Trigger a function in a controller with Karma

In an angular controller I have a function on my scope that looks like this:
$scope.myFunction = function(val) {
$scope.myVar = val;
$scope.mySettings.myPath = $scope.myBase + $scope.myVar;
}
In my karma unit test I want to trigger that function on the controller using a value i supply ... then check $scope.mySettings.myPath to make sure it is what i think it should be.
Im trying this in karma:
describe("Unit Testing: Controller Testing" , function() {
describe('myController' , function () {
var scope,ctrl;
beforeEach(module('myApp.controllers'));
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
ctrl = $controller('myController', {
$scope: scope
});
}));
it('should have a working changeVideo function' , function(){
scope.changeVideo(scope.myVar[6]);
expect(scope.mySettings.myPath).to.equal('Expected String');
});
});
});
The error i see is that it cannot call equal method of undefined. Which is odd because scope.mySettings.myPath is actually predefined in the controller so it should never be undefined.
To give some background I do have access to the controller and the scope from karma. This one is stumping me though.
The solution to this was using toEqual() instead of to.equal()

Resources