Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular JS Testing with Karma Jasmine

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.

like image 228
StrugglingCoder Avatar asked Jan 25 '17 04:01

StrugglingCoder


1 Answers

Original Error:

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)

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.

like image 200
Matt M Avatar answered Oct 16 '22 09:10

Matt M