0

I am new in writing unit test case using jasmine. I am trying to test a resource based service in a controller fetching real data from server but not getting the desired results. Please provide your inputs where I am doing wrong. Below is the unit test I have written : describe('NewStarterController', function() { beforeEach(module('myApp')); var scope, ctrl, $resource;

       var context = 'http://localhost.com:8085/AngularPrototype/home';

       beforeEach(inject(function(_$resource_, $rootScope, $controller) {
              $resource = _$resource_;

              NewStarter = {
                     getNSData : function() {
                           return $resource(context + '/selfservice/newstarter/get', {}, {
                                  get : {
                                         method : 'GET'
                                  }
                           });
                     }
              };
              scope = $rootScope.$new();

              $controller('NewStarterController', {
                     $scope : scope,
                     NewStarter : NewStarter
              });

       }));

       it('should test new starter data', function() {

              NewStarter.getNSData().get({}).$promise.then(function(response) {
                     scope.refData = response;
                     scope.data();

              });


              expect(scope.data.length).toEqual(2);

              expect(NewStarter.getNSData().get.length).toEqual(2);

              expect(NewStarter.getNSData().get()).toEqual('formTitleNode');

       });

}); 



Below is the jasmine test result ::

Jasmine 1.3.1 revision 1354556913finished in 0.183s
•   
No try/catchFailing 1 spec1 spec | 1 failing
NewStarterController
should test new starter data
NewStarterController should test new starter data.
Expected 0 to equal 2.
Expected 4 to equal 2.
Expected { $promise : { $$state : { status : 0 } }, $resolved : false } to equal 'formTitleNode'.





get.json      ->   represents the data that is returned from server(Data returned from RestController) on hitting the url : http://localhost.com:8085/AngularPrototype/home/selfservice/newstarter/get

SpecRunner.html->  is used to run the jasmine unit test. Below are the contents of this file :
<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Jasmine Demo</title>

    <script>
        libraries here
    </script>
</head>
<body>
<!-- Include Angular and Angular Mocks-->
<script>libraries here </script>
    <!-- Include your source files here... -->
<script src="services/services.js"></script>
<script src="myApp.js"></script>
<script src="controller/selfservice/NewStarterController.js"></script>

<!-- Include your spec files here... -->
<script src="jasmineunittest/NewStarterControllerTest.js"></script>


<!-- Jasmine execution script (Standard Jasmine Bolierplate)-->
<script type="text/javascript">
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.execute();

</script>

</body>
</html> 


Below is the controller code ( NewStarterController.js ) which is unit tested : 

myApp.controller("NewStarterController", ['$scope','$modal', '$state', '$sce', 'NewStarter', function($scope,$modal, $state, $sce, NewStarter) {


       $scope.data = function() {
              NewStarter.getNSData().get({}, function(response) {
                     $scope.refData = response;
                     $scope.formTitle = [];
                     $scope.displayOptions = [];
                     angular.forEach($scope.refData.formTitleNode, function(contentItem)
                     {
                           var content = -1;
                           var title = -1;
                           angular.forEach(contentItem.fieldList, function(fieldBean)
                           {
                                  if(fieldBean.fieldName == 'TITLE')
                                  {
                                         title = fieldBean.fieldValue;

                                  }
                                  if(fieldBean.fieldName == 'FORMATTEDCONTENTS')
                                  {
                                         content = fieldBean.fieldValue;

                                  }
                           })
                           $scope.formTitle.push({title:title, content:content});
                     })

                     angular.forEach($scope.refData.displayOptionsNode, function(contentItem)
                     {

                           var nsContent = -1;
                           var nsTitle = -1;
                           angular.forEach(contentItem.fieldList, function(fieldBean)
                           {
                                  if(fieldBean.fieldName == 'TITLE')
                                  {
                                         nsTitle = fieldBean.fieldValue;

                                  }
                                  if(fieldBean.fieldName == 'FORMATTEDCONTENTS')
                                  {
                                         nsContent = fieldBean.fieldValue;

                                  }
                           })
                           $scope.displayOptions.push({nsTitle:nsTitle, nsContent:nsContent});
                           $scope.selectedOption = '';
                     })

                     $scope.hasNewStarterSubmitted = $scope.refData.hasNewStarterSubmitted;
                     $scope.submittedSelectedOption = $scope.refData.submittedSelectedOption;
                     $scope.submittedStudentLoan = $scope.refData.submittedStudentLoan;
                     $scope.nsAlreadySubmittedValidationMsg = $scope.refData.nsAlreadySubmittedValidationMsg;



                     console.log('Success', response);
              }, function(error) {
                     //alert(JSON.stringfy(error))
                     $scope.contentLoadErrorMsg=error.data;
                     //console.error('ERR', error);
              });
       }
}]);





Below is the code in services.js

myApp.factory('NewStarter', function($resource, context) {
       return {
              getNSData: function() {
                     return $resource(context + '/selfservice/newstarter/get', {}, {get: {method:'GET'}});
              },
              submitNSForm: function() {
                     return $resource(context + '/selfservice/newstarter/submit', {}, {submit: {method:'POST'}});
              }

       }
});


Below is the code in myApp.js 

var myApp = angular.module('myApp', ['ngResource', 'ngSanitize', 'ui.bootstrap', 'ui.router']);

myApp.constant('context', '/AngularPrototype/home');
myApp.constant('projectName', '/AngularPrototype');
myApp.config(function($stateProvider, $urlRouterProvider, projectName) {
$urlRouterProvider.otherwise('/home');

$stateProvider .state('newStarter', {
                     url:'/newstarter',
                     templateUrl: projectName + '/newstarter',
                     controller: 'NewStarterController'
              })
});


 Thanks!  



Below i tried as per your suggestion but getting error while running the unit test:
describe('NewStarterController', function() { 
beforeEach(module('myApp')); 
var scope, postDefer,NewStarter;



       beforeEach(inject(function(_NewStarter_, $rootScope, $controller,$q) {
              NewStarter = _NewStarter_;
             postDefer = $q.defer();
             spyOn(NewStarter,'getNSData').and.returnValue(postDefer.promise);
              scope = $rootScope.$new();

              $controller('NewStarterController', {
                     $scope : scope,
                     NewStarter : NewStarter
              });

       }));

       it('should test new starter data', function() {

              NewStarter.getNSData().get({});
              postDefer.resolve();
              scope.$apply();

              expect(scope.data.length).toEqual(2);

       });

}); 


Below are the errors while running the test :

Error:[$injector:unpr] Unknown provider: NewStarterProvider <- NewStarter
typeError: Unable to get property 'getNSData' of undefined or null reference
4
  • your mock getNSData doesn't have to call $resource, just return a promise instead, and resolve the promise when you need to verify the result. Check my answer on other question stackoverflow.com/questions/36189329/… Commented Apr 7, 2016 at 4:53
  • I tried as per your suggestion but it did not work. getNSData method was not recognized. Can you please share the code?? Thanks! Commented Apr 12, 2016 at 15:11
  • Can you update you question with the code that you tried as per my suggestion? Commented Apr 12, 2016 at 23:58
  • updated the question with the code i tried and mentioned the error also which i am getting while running the unit test. Please take a look and provide your valuable inputs. Thanks! Commented Apr 13, 2016 at 14:58

1 Answer 1

0

Since it is a unit test, you need to focus on testing the single unit, you should try to mock all dependencies as much as possible. Having say that, using real $resource in your unit test is not desirable.

What I think you should do is: - 1. Mock NewStarter.getNSData(), or whatever service methods get called in controller 2. Return a fake resource object 3. mock get method of the fake resource (as it is what's used in your controller) and return a promise 4. resolve the promise to test your success handler.

Check out this plunker http://plnkr.co/edit/8l3mY1?p=preview

var  mockResource = {get: function(){}}, $q;
beforeEach(inject(function($rootScope, $controller, _$q_, NewStarter) {
  $scope = $rootScope.$new();
  $q = _$q_;
  spyOn(NewStarter, 'getNSData').and.callFake(function() {
     return mockResource;
  });

  ctrl = $controller('MainCtrl', {
    $scope: $scope
  });
}));

it('should return value', function() {
  var responseObj = {id: 1, name:'test'};
  spyOn(mockResource, 'get').and.callFake(function(data, func){
      var deferred = $q.defer();
      deferred.resolve(responseObj);
      return deferred.promise.then(func);
    });

  $scope.data();

  expect(mockResource.get).toHaveBeenCalled();  
  $scope.$apply();

  expect($scope.refData).toEqual(responseObj);
});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.