Angular is a controller testing block that promises initialization. (Jasmine)

You have a controller ExampleController

that uses a service method RequestService.data

during its initialization and you just want to check that the controller (scope) .property is set to a value in the response:

ExampleController:

app.controller('ExampleController'
            , ['$scope','RequestService', function($scope, RequestService){
  var ex = this;  
  (function initialize(){
    RequestService.
      data().
      then(function RSresp(info){
       ex.property = info.data.property;
      }
  })();
}]

      

RequestService:

app.service('RequestService', ['$http', function($http){
   this.data = function RSdata(){
     var closure = {prop: 'val', derp: 'aderp'};
     var url = 'http://aWebsite.' + closure.prop + '.com/' + closure.derp;
     return $http.get(url);
   }
}]);

      

Unit test:

describe('on initialization, ExampleController',function(){
 var controller, injector, $httpBackend, $scope, RequestService;

  beforeEach(function(){
   inject(function(_$injector_, _$controller_, _$rootScope_){
     injector = _$injector_;
     $scope = _$rootScope_.new();
     $httpBackend = injector.get('$httpBackend');
     controller = _$controller_('ExampleController', {$scope : $scope});
     RequestService = injector.get('RequestService');
   })
  })

  beforeEach(function(){
    $httpBackend.
       when('GET', 'http://aWebsite.val.com/aderp').
       respond({property: 'value'});
  });

  afterEach(function(){
    $httpBackend.verifyNoOutstandingExpectation();
    $httpBackend.verifyNoOutstandingRequest();
  });

  it('has a property "property" with a value "value" ', function(){
    expect(controller.property).toBeDefined();
    expect(controller.property).toBe('value');
  });
});

      


I've tried a bunch of different things like:

expect($scope.property).toBeDefined();

      

or

spyOn(RequestService, 'data');
// or spyOn(RequestService, 'data').andCallThrough();
expect(controller.property).toBeDefined();
expect(RequestService.data).toHaveBeenCalled;

      


Karma says:

"Error: Unflushed requests"


or
on initialization, ExampleController has a property "property" with a value "value" Fail: undefined is not defined.

console.log(controller)

doesn't show that the property is set and it doesn't look like the RequestService is ever called ...

I dont know. All my tests for the RequestService pass and the application itself works ... but I can't figure out how to write a spec to reflect this.

I looked at: Unit tests promises in controllers in AngularJS

and some others that didn't turn out to be irrelevant ... but no luck

+3


source to share


2 answers


Your tests are doing too much at the moment.

The responsibility for testing your queries $http

should be a test for yours RequestService

. When testing anything that causes RequestService

, you mock RequestService

.

In general, do not execute more than 1 dependency in unit tests (so ExampleController

→ RequestService

will be your limit). Your integration tests will be responsible for testing the complete sequence.



So your unit tests should look something like this:

describe('on initialization, ExampleController',function(){
 var $q, $controller, injector, $scope, RequestService;

  beforeEach(function(){
    inject(function(_$q_, _$injector_, _$controller_, _$rootScope_){
      $q = _$q_;
      injector = _$injector_;
      $controller = _$controller_;
      $scope = _$rootScope_.$new();
      RequestService = injector.get('RequestService');
    });
  });

  beforeEach(function(){
    spyOn(RequestService, 'data');
  });

  describe('with successful data retrieval', function () {
    beforeEach(function () {
      // mock a success
      RequestService.data.andReturn($q.when({property: 'value'}));
      controller = $controller('ExampleController', {$scope : $scope});

      $scope.$digest(); // fulfil the promises
    });

    it('has a property "property" with a value "value" ', function(){
      expect(controller.property).toBeDefined();
      expect(controller.property).toBe('value');
    });
  });

  describe('with failed data retrieval', function () {
    beforeEach(function () {
      // mock a fail
      RequestService.data.andReturn($q.reject(null));
      controller = $controller('ExampleController', {$scope : $scope});

      $scope.$digest(); // fulfill the promises
    });

    it('should do something', function(){
      expect('this').toBe('that');
    });
  });
});

      

+3


source


The solution to this problem was to call $ digest.



0


source







All Articles