AngularJs controller test: unexpected request : GET - angularjs

I am trying to write my first test for controller by mocking the service layer using karma-jasmine and httpBackend. But I am getting this error.
Error: Unexpected request: GET./webresources/campaign/getCampaignDetails/undefined
Expected GET ./webresources/campaign/getCampaignDetails/CMP1000004568
Thanks in advance for any help :)
Service:
(function() {
'use strict';
angular.module('tbApp').factory('Campaign', CampaignFactory);
CampaignFactory.inject = ['$http'];
function CampaignFactory($http) {
//base url for all rest service calls
var baseUrl = WS_PATH + '/webresources/campaign';
var Campaign = {
getCampaignDetails: getCampaignDetails,
};
return Campaign;
function getCampaignDetails(campaignId) {
return $http.get(baseUrl + '/getCampaignDetails/' + campaignId).then(getCampaignDetailsComplete);
function getCampaignDetailsComplete(response) {
return response.data;
}
}
}
})();
Controller:
(function () {
'use strict';
angular.module('tbApp').controller('campaignEditCtrl', campaignEditCtrl);
campaignEditCtrl.inject = ['$routeParams', 'Campaign', 'User', '$location', 'Asset', '$window', '$scope', '$compile', 'ImageLibrary', 'Lists'];
function campaignEditCtrl($routeParams, Campaign, User, $location, Asset, $window, $scope, $compile, ImageLibrary, Lists) {
var vm = this;
vm.campaignData = [];
vm.getCampaignDetails = getCampaignDetails;
initialise();
/**
* Initialises the campaign properties page
*/
function initialise() {
// Registes a click listener to hide action menu
$window.addEventListener('click', function (event) {
if (event.which !== 3) {
$scope.$apply(function () {
vm.selectedActionItem = '';
});
}
});
fromPage=true;
fromPage1=true;
vm.user = User.info;
vm.campaignId = $routeParams.campId;
//set default value to prevent filter error
vm.campaignData.imageName = '///////';
getCampaignDetails();
getAllImageData();
}
/**
* Load the campaign details
*/
function getCampaignDetails() {
vm.loadingCampaignDetails = true;
Campaign.getCampaignDetails(vm.campaignId).then(getCampaignDetailsComplete);
function getCampaignDetailsComplete(data) {
vm.campaignData = data;
}
}
}})();
controllerSpec:
describe('campaignEditCtrl as vm', function() {
var scope, httpBackend, controller, vm, createController, campaignId;
var baseUrl = './webresources/campaign';
beforeEach(module("tbApp"));
beforeEach(inject(function($rootScope, $httpBackend, $controller) {
httpBackend = $httpBackend;
scope = $rootScope.$new();
controller = $controller;
campaignId= "CMP1000004568";
//service = Campaign;
createController = function() {
return $controller('campaignEditCtrl', {
'$scope': scope
});
};
httpBackend.when("GET", baseUrl+"/getCampaignDetails/"+campaignId).respond([{}, {}, {}]);
}));
/*afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});*/
it('should run the Test to get the campaign data from the backend', function() {
console.log("here"+campaignId);
vm=createController();
httpBackend.expectGET(baseUrl+"/getCampaignDetails/"+campaignId);
scope.$apply(function() {
scope.runTest();
});
//expect(vm.campaignData.imageName).toEqual('///////');
httpBackend.flush();
expect(vm.campaignData.length).toBe(3);
});
});
Output:
INFO [karma]: Karma v0.12.31 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.8 (Windows 7)]: Connected on socket jAWt7tfOMUkrmCjM0d_n with id 71764124
INFO [Chrome 41.0.2272 (Windows 7)]: Connected on socket Fu0mS3U91St4gSQ10d_o with id 78282639
WARN [web-server]: 404: /webresources/user/checkSession
PhantomJS 1.9.8 (Windows 7) LOG: 'WARNING: Tried to load angular more than once.'
LOG: 'hereCMP1000004568'
PhantomJS 1.9.8 (Windows 7) campaignEditCtrl as vm should run the Test to get the campaign data from the backend FAILED
Error: Unexpected request: GET ./webresources/campaign/getCampaignDetails/undefined
Expected GET ./webresources/campaign/getCampaignDetails/CMP1000004568
at $httpBackend (D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/angular-mocks.js:1181)
at sendReq (D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:8404)
at D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:8123
at D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:11659
at D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:11659
at D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:11745
at D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:12788
at D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:12600
at D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:12892
at D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/test/js/campaignEditSpec.js:42
at D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/node_modules/karma-jasmine/lib/boot.js:117
at D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/node_modules/karma-jasmine/lib/adapter.js:171
at http://localhost:9876/karma.js:185
at http://localhost:9876/context.html:157
PhantomJS 1.9.8 (Windows 7): Executed 2 of 2 (1 FAILED) (0.008 secs / 0.024 secs)
LOG: 'WARNING: Tried to load angular more than once.'
Chrome 41.0.2272 (Windows 7) LOG: 'hereCMP1000004568'
Chrome 41.0.2272 (Windows 7) campaignEditCtrl as vm should run the Test to get the campaign data from the backend FAILED
Error: Unexpected request: GET ./webresources/campaign/getCampaignDetails/undefined
Expected GET ./webresources/campaign/getCampaignDetails/CMP1000004568
at $httpBackend (D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/angular-mocks.js:1180:9)
at sendReq (D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:8403:9)
at serverRequest (D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:8123:16)
at wrappedCallback (D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:11659:8
at wrappedCallback (D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:11659:8
at D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:11745:26
at Scope.$eval (D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:12788:28)
at Scope.$digest (D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:12600:31)
at Scope.$apply (D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/main/webapp/js/libraries/uncompressed/angular.js:12892:24)
at Object.<anonymous> (D:/Tb_test/Campaign_Builder_Maven/campaign-builder-webapp/src/test/js/campaignEditSpec.js:40:9)
PhantomJS 1.9.8 (Windows 7): Executed 2 of 2 (1 FAILED) (0.008 secs / 0.024 secs)
Chrome 41.0.2272 (Windows 7): Executed 2 of 2 (1 FAILED) (0.051 secs / 0.047 secs)
TOTAL: 2 FAILED, 2 SUCCESS

We can see in the karma output that the test is failing because the URL is wrong. Instead of a campaign id, you're getting undefined.
Chrome 41.0.2272 (Windows 7) campaignEditCtrl as vm should run the Test to get the campaign data from the backend FAILED
Error: Unexpected request: GET ./webresources/campaign/getCampaignDetails/undefined
Expected GET ./webresources/campaign/getCampaignDetails/CMP1000004568
It looks like you're trying to test your getCampaignDetails() function, which passes in vm.campaignId as an argument to your service call. However, in your test you don't set vm.campaignId to anything before calling your function.
In your test setup, I would try changing your code to this:
scope = $rootScope.$new();
controller = $controller;
campaignId= "CMP1000004568";
//service = Campaign;
createController = function() {
var controller = $controller('campaignEditCtrl', {
'$scope': scope
});
scope.vm.campaignId = campaignId;
return controller;
};
...and see if that fixes it.
What's going on here is that your getCampaignDetails() function's behavior is dependent on the state of your controller. Your controller has an initialize() function that brings your controller to a state where the getCampaignDetails() can succeed. In your test, however, you don't perform similar initialization.

Related

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)

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

Issues unit testing controllerAs: logging controller returns a promise

I'm trying to test a controller which uses the controllerAs syntax. My problem is that when I try to test a function on the controller, I get "Expected undefined to be defined."
Controller (shortened version)
(function (angular) {
'use strict';
/* #ngInject */
function PreflightCtrl($state, $window, $timeout, $stateParams, toastr, accountService, servicesService, geoService, visitService, localStorageService, Notifications, service, UTILS) {
/* Exported Vars */
var vm = this;
/* Exported functions */
vm.verifyDob = verifyDob;
function verifyDob() {
if (!vm.form.dob || (vm.form.dob.length !== 8 && vm.form.dob.length !== 10)){
return;
}
if(vm.form.dob.length === 8){
var lastTwoDigits = vm.form.dob.substr(vm.form.dob.length-2);
if(lastTwoDigits === '19'){
return;
}
}
var dob = new Date(vm.form.dob);
vm.verifyingDob = true;
accountService.verifyDOB(dob)
.success(function(data){
vm.genderDisabled = false;
vm.dobError = false;
$timeout(function() {
dobInput.blur();
});
})
.error(function (status) {
vm.genderDisabled = true;
vm.dobError = true;
})
.finally(function () {
vm.verifyingDob = false;
});
}
}
angular
.module('app')
.controller('PreflightCtrl', PreflightCtrl);
}(angular));
Test
describe('PreflightCtrl', function(){
var PreflightCtrl, $state, $window, $timeout, $stateParams, toastr, accountService, servicesService, geoService, visitService, localStorageService, Notifications, service, UTILS, mockAccountService, mockServicesService;
beforeEach(module('app'));
beforeEach(inject(function($controller, _$state_, _$window_, _$timeout_, _$stateParams_, _toastr_, _accountService_, _servicesService_, _geoService_, _visitService_, _localStorageService_, _Notifications_, _UTILS_){
//mock services used in PreflightCtrl
mockAccountService = {
verifyDOB: function verifyDOB(dob){
return {
success: function(callback){
callback(dob);
}
}
},
isPermUser: function isPermUser(){
return {
success: function(callback){
callback(true);
}
}
},
profile: {
gender: 'male'
}
};
mockServicesService = {
isGenderAllowed: function isGenderAllowed(serviceCode, gender){
return true;
}
}
//prepare for dependency injection
$state = _$state_;
$window = _$window_;
$timeout = _$timeout_;
$stateParams = _$stateParams_;
toastr = _toastr_;
accountService = mockAccountService;
servicesService = mockServicesService;
geoService = _geoService_;
visitService = _visitService_;
localStorageService = _localStorageService_;
Notifications = _Notifications_;
service = {"id": 3, "code": "HL", "flags": {"multi_medicine": false}, "genders": ["male"], "name": "Hair Loss", "product": {"count": 3}, "visible": 1};
UTILS = _UTILS_;
//spy on the mocked services
spyOn(accountService, 'verifyDOB').and.callThrough();
spyOn(servicesService, 'isGenderAllowed').and.callThrough();
//create the controller
PreflightCtrl = $controller('PreflightCtrl', {
$state: $state,
$window: $window,
$timeout: $timeout,
$stateParams: $stateParams,
toastr: toastr,
accountService: accountService,
servicesService: servicesService,
geoService: geoService,
visitService: visitService,
localStorageService: localStorageService,
Notifications: Notifications,
service: service,
UTILS: UTILS
});
}));
it('should have a defined controller', function(){
expect(PreflightCtrl).toBeDefined();
});
it('should have a defined function called verifyDob', function(){
console.log(PreflightCtrl);
expect(PreflightCtrl.verifyDob).toBeDefined();
});
it('should verify a DOB', function(){
PreflightCtrl.form.dob = '01/01/1990';
PreflightCtrl.verifyDob();
expect(PreflightCtrl.verifyingDob).toBe(false);
});
});
When I run the test, this is the output that I get:
Running "karma:unit" (karma) task
PhantomJS 1.9.8 (Mac OS X 0.0.0) LOG: 'WARNING: Tried to load angular more than once.'
LOG: Promise{$$state: Object{status: 2, value: Error{message: ...}}}
PhantomJS 1.9.8 (Mac OS X 0.0.0) PreflightCtrl should have a defined function called verifyDob FAILED
Expected undefined to be defined.
at /Users/tracy/Projects/LemonaidClinic/src/views/preflight/preflight.controller.spec.js:80
PhantomJS 1.9.8 (Mac OS X 0.0.0) PreflightCtrl should verify a DOB FAILED
TypeError: 'undefined' is not an object (evaluating 'PreflightCtrl.form.dob = '01/01/1990'')
at /Users/tracy/Projects/LemonaidClinic/src/views/preflight/preflight.controller.spec.js:85
PhantomJS 1.9.8 (Mac OS X 0.0.0): Executed 15 of 15 (2 FAILED) (0.006 secs / 0.204 secs)
Warning: Task "karma:unit" failed. Use --force to continue.
Aborted due to warnings.
Line 80 is this line: expect(PreflightCtrl.verifyDob).toBeDefined();
and line 85 is this: PreflightCtrl.form.dob = '01/01/1990';
and you can see the first line is the log of the controller, which returns a promise which means none of the functions or variables are on the controller that need to be there.
I'm also unsure why Angular is trying to load more than once, but it doesn't seem to be affecting any other tests.
What am I doing wrong?
Thank you in advance.
I would do it more like this:
var scope = $rootScope.$new();
$controller('myController as vm', {$scope:scope, /*your dependency tree hell*/});
$rootScope.$apply();
vm = scope.vm;//This is your new controller, you can refer to it in tests.
I think the fact that you have to mock so much says your Controller has too many dependencies, directly and/or indirectly.
However, if you're not in a position to fix that, you can mock more easily by just creating a folder called "mocks" and dropping in files that have the same id as the real ones and pointing Karma to that folder. Those will override the actual dependencies. The downside is that you'll still have to do one-off mocks if you need something different than your registered mock, but it removes the task of having to set up mocks in each test.

Jasmine Testing with vm in Angular controller

Trying to test a simple test in Jasmine & Karma and AngularJs frameWork,
controller:
(function() {
'use strict';
angular
.module('bsp.account')
.controller('Account', Account);
/* #ngInject */
function Account(userService, accountService) {
var vm = this;
vm.title = 'Accounts';
vm.username = userService.getUsername();
vm.showPasswordModal = accountService.showPasswordModal;
vm.showLogoutModal = accountService.showLogoutModal;
activate();
////////////////
function activate() {
}
}
})();
Can anyOne tell me how do i write a simple test case using Jasmin with this code ? and also maybe a possible methode and its test,
My test code below:
describe('Account', function() {
var scope,
controller;
beforeEach(module('bsp.account'));
//sample testCase--
it('testCheck', function() {
expect('helloWorld').toBe("helloWorld");
});
describe('Account', function() {
//injecting the scope&controller--
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('Account', {
$scope: scope
});
scope.vm = controller;
}));
});
it("checkTitle",function(){
var vm = controller("Account",{$scope:scope});
expect(vm.title).toEqual("Accounts");
});
});
karma ,response:
Running "karma:unit:run" (karma) task
[2015-10-23 15:11:03.542] [DEBUG] config - Loading config /vagrant/frontend/build/karma-unit.js
✗ checkTitle
TypeError: 'undefined' is not a function (evaluating 'controller("Account",{$scope:scope})')
at /vagrant/frontend/src/app/account/account.controller.spec.js:33
LOG LOG: undefined
PhantomJS 1.9.8 (Linux 0.0.0) LOG: undefined
LOG LOG: '** if *********'
PhantomJS 1.9.8 (Linux 0.0.0) LOG: '** if *********'
PhantomJS 1.9.8 (Linux 0.0.0): Executed 37 of 37 (1 FAILED) (0.134 secs / 0.128 secs)
Warning: Task "karma:unit:run" failed. Use --force to continue.
Aborted due to warnings.
Completed in 10.849s at Fri Oct 23 2015 15:11:04 GMT-0700 (PDT) - Waiting...
Any suggestions is appreciated,Am new to Jasmin testing.Thank You
You are actually instantiating a BoardPerformance controller in your beforeEach block but the code you are showing is for Account, so I understand that's a mistake.
So for your simple test case to run try this:
describe('Account', function() {
var scope, controller, userServiceMock;
beforeEach(module('bsp'));
beforeEach(function() {
userServiceMock = {
getUsername: function(){}
}
});
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('Account', {
'userService': userServiceMock
});
}));
it('checkTitle', function(){
expect(controller.title).toEqual('Accounts');
});
});
So this is the new test case in Jasmin,
describe('Account', function() {
var scope, controller, userServiceMock,accountServiceMock;
beforeEach(module('bsp'));
beforeEach(function() {
userServiceMock = {
getUsername: function(){} //this is a method inside userService
};
accountServiceMock = {
showPasswordModal :function(){}//this is a method inside accountService
};
});
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('Account', {
'userService': userServiceMock,
'accountService':accountServiceMock
});
}));
describe('testing Title',function(){
it('checkTitle', function(){
expect(controller.title).toEqual('Accounts');
});
});
});
It is very basic but has necessary information for controllers with dependency and also the vm..thank to Pablo

How to write a Karma test to see if a factory function is being called by a controller in Angular?

I'm learning to use Karma and Jasmine for unit-testing in Angular, and am trying to determine how to properly mock out a factory and test that it is called by a controller. The factory makes a simple http request from the ESPN API. When the controller calls it, it passes the response data to an array. What I have so far is based off of this: Angular unit-test controllers - mocking service inside controller. Unfortunately I just can't seem to get it right.
Here is what my controller and factory look like:
angular.module('TeamApp.services',[])
.factory('espnAPIservice',function($http) {
var espnAPI = {};
espnAPI.getTeams = function() {
return $http({
method: 'GET',
url: 'http://api.espn.com/v1/sports/hockey/nhl/teams?'
})
}
return espnAPI;
});
//Calls the espnAPIservice and stores the retrieved information in an array
angular.module('TeamApp.controllers',[])
.controller('TeamCtrl', ['$scope','espnAPIservice',function($scope,espnAPIservice) {
$scope.teams = [];
espnAPIservice.getTeams().success(function (response) {
$scope.teams = response;
});
}]);
angular.module('TeamApp',['TeamApp.services','TeamApp.controllers']);
Here is my test for it so far:
describe('controller: TeamCtrl', function() {
var $scope, ctrl;
//Inject controller module into the factory that it the controller will call
beforeEach(module('TeamApp.controllers', function($provide) {
var espnAPIservice = {
getTeams: function(){}
};
spyOn(espnAPIservice,'getTeams').andReturn('ESPN'); //change return value
$provide.value('espnAPIservice',espnAPIservice);
}));
//Inject the $controller and $rootScope services
beforeEach(inject(function($rootScope, $controller, espnAPIservice) {
//Create a new scope that is the child of $rootScope
$scope = $rootScope.$new();
//Create the controller
ctrl = $controller('TeamCtrl',{$scope: $scope, espnAPIservice: espnAPIservice});
}));
it('should call the getTeams function', function(){
expect($scope.teams).toBe('ESPN');
});
And here is the error I get when I run the test:
PhantomJS 1.9.7 (Windows 7) controller: TeamCtrl should call the getTeams function FAILED
TypeError: 'undefined' is not a function (evaluating 'espnAPIservice.getTeams().success(function (response) {
$scope.teams = response;
})')
at c:/Users/jquering/Documents/Coding Practice/Angular Practice/nhlStats/app/scripts/teams.js:21
at invoke (c:/Users/jquering/Documents/Coding Practice/Angular Practice/nhlStats/app/lib/angular.js:3762)
at instantiate (c:/Users/jquering/Documents/Coding Practice/Angular Practice/nhlStats/app/lib/angular.js:3773)
at c:/Users/jquering/Documents/Coding Practice/Angular Practice/nhlStats/app/lib/angular.js:6884
at c:/Users/jquering/Documents/Coding Practice/Angular Practice/nhlStats/test/controllers/spec/main.js:18
at invoke (c:/Users/jquering/Documents/Coding Practice/Angular Practice/nhlStats/app/lib/angular.js:3762)
at workFn (c:/Users/jquering/Documents/Coding Practice/Angular Practice/nhlStats/app/lib/angular-mocks.js:2144)
undefined
Expected [ ] to be 'ESPN'.
PhantomJS 1.9.7 (Windows 7): Executed 1 of 1 (1 FAILED) ERROR (0.009 secs / 0.008 secs)
Any help would be much appreciated!
how to properly mock out a factory
beforeEach(module(function ($provide){
$provide.factory('TheSameName', function (){
//return your mock here
});
}));

Resources