Thursday, February 2, 2017

Angular JS Testing with Karma Jasmine

Leave a Comment

I have a sample route like this :

  angular         .module('appRouter',['ui.router'])         .config(function($stateProvider,$urlRouterProvider){             $stateProvider                 .....                 .....                 .state('settings.account',{                     url:'/account',                     templateUrl:'templates/account.html',                     controller:function(resolveData){                         console.log(resolveData);                     },                     resolve:{                         resolveData : function($http){                             var root = 'https://jsonplaceholder.typicode.com';                             return $http.get(root+'/posts/1').then(function(response){                                  return response.data;                             });                         }                     }                 });              ..... 

It is just a test URL where I can get sample JSON data online

https://jsonplaceholder.typicode.com/posts/1

I wanted to test the state.

  beforeEach(function(){         module('appRouter');     });      beforeEach(inject(function(_$rootScope_,_$injector_,_$state_,_$httpBackend_,$templateCache){         $rootScope = _$rootScope_;         $state = _$state_;         $injector = _$injector_;         $httpBackend = _$httpBackend_;         $templateCache.put('templates/account.html','');     }));     it('should resolve "resolveData"',function(){         const state = $state.get('settings.account');         const resolveFn = state.resolve.resolveData;                  $httpBackend.whenGET('https://jsonplaceholder.typicode.com/posts/1').respond(function(){         return [             200,{                 "userId": 1,                 "id": 1,                 "title": "...",                 "body": "..."         }]     });      $httpBackend.expectGET('https://jsonplaceholder.typicode.com/posts/1');      $injector.invoke(resolveFn);      $httpBackend.flush();      expect($injector.annotate(resolveFn)).toEqual(['$http']);      console.log(angular.mock.dump($scope));      expect($scope.resolveData).toEqual({          "userId": 1,          "id": 1,          "title": "...",          "body": "..."      }); 

But this fails. Saying

1) should resolve "resolveData"      UI Routerer Config For Account      Expected undefined to equal Object({ userId: 1, id: 1, title: '...', body: '...' }).     at Object.<anonymous> (test/controllers/main-controller-spec.js:114:36) 

What am I doing wrong ?

UPDATE

console.log(angular.mock.dump($scope)); gives the following

enter image description here

Please help.

2 Answers

Answers 1

What am I doing wrong?

You are calling resolveFn() in your unit test. The function was defined as requiring the $http service, and that call does not pass the $http service (as fingerpich mentioned).

To correct this, allow angular to handle the dependency injection by using $injector.invoke(resolveFn).

See this in action with a plunk. Note the test does fail for a different reason. But, (if I understand the rules correctly) that is a different issue should be answered with a different question (if you need more help).

A side note: When the site (not the unit test) is opened in a browser, I would expect it to work, because angular injects the $http dependency into the function assigned to resolveData.

Look at answer that also references the blog mentioned by fingerpich.

Here is a blog I found helpful when learning about unit testing AngularJS.

Answers 2

should resolve "resolveData" UI Routerer Config For Account TypeError: Cannot read property 'get' of undefined  at resolveData (app/appRouter.js:25:41)  at Object.<anonymous> (test/controllers/main-controller-spec.js:97:9) 

to solve this problem you should pass $http to resolveData function.

resolveFn($http);  

but it's better to write tests like this

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment