2

I'm trying to test a service in my AngularJS project. All I'm trying to do is see if the method on my service has called through. I thought that when you use 'and.callThrough()' in jasmine it called the method for you and then you can see if it was called. However, when I test my function karma is giving me the response of 'Expected spy of getArtists to have been called'.

describe('Practice', function(){
 beforeEach(module('MyApp'));
 var ctrl, loadArtists, rootscope, dataFactory;
 beforeEach(inject(function($controller, $rootScope, DataFactory){
    spyOn(DataFactory, 'getArtists').and.callThrough();
    dataFactory = DataFactory
    rootscope = $rootScope;
    scope = rootscope.$new();
    ctrl = $controller('LaunchCtrl',{scope: scope, artistsPicsRotate: []});
}));

it('should do nothing',function(){
    expect(ctrl.artistsPicsRotate).toEqual([])
});

it('should call through DataFactory', function(){
    expect(dataFactory.getArtists).toHaveBeenCalled();
    expect(dataFactory.getArtists.calls.count()).toEqual(1);
});

});

Any ideas on why this isn't working would be much appreciated.

2K01B5
  • 1,011
  • 1
  • 10
  • 23
  • Can you post the code for the controller that your are trying to test. Do you have call to the service inside the controller? – S.Klechkovski Oct 10 '15 at 10:05
  • I pass the promise returned from the factory into the routing resolve and sort the data. From there I pass the response to the controller and display the data. Should I post the controller, factory and resolve? – 2K01B5 Oct 10 '15 at 10:19
  • 1
    That means your controller never explicitly calls DataService.getArtists(), because the call is done when the routing state is resolved and you receive the result injected in the controller. So when testing the controller you don't need to test the call to the service because that call is not directly made from the controller. – S.Klechkovski Oct 10 '15 at 10:26
  • Ok thanks. How would I test DataFactory.getArtists() to see if it has been called through because I thought that the spyOn would just watch the DataFactory.getArtists() and check whether it was called at all not whether it was called in the controller? Also, do you know of any good documentation for testing routing resolves because it's making it hard for me to test my project generally. Again thanks for the help. – 2K01B5 Oct 10 '15 at 10:33

1 Answers1

2

As explained in the comments the call to the service is done by the ui-router resolves before the controller is instantiated. That means the controller never explicitly calls DataService.getArtists(), because the call is done when the routing state is resolved and the received result is injected in the controller. So when testing the controller there is no need to test the call to the service because that call is not directly made from it.

However if you want to test the state definition here is one example how you can do it.

describe('Practice', function(){
  beforeEach(module('MyApp'));
  var ctrl, loadArtists, rootscope, dataFactory, $state;
  beforeEach(inject(function($controller, $rootScope, DataFactory, _$state_){
    dataFactory = DataFactory
    rootscope = $rootScope;
    scope = rootscope.$new();
    $state = _$state_;
    ctrl = $controller('LaunchCtrl',{scope: scope, artistsPicsRotate: []});
  }));

  it('should do nothing',function(){
      expect(ctrl.artistsPicsRotate).toEqual([])
  });

  // NOTE: test your state definition
  describe('state definition', function () {

    var stateDefinition;
    beforeEach(function () {
      stateDefinition = $state.get('stateName');
    });

    // NOTE: write test for each resolve
    it('should resolve artists', function() {
      // given
      spyOn(dataFactory, 'getArtists').and.callThrough();

      // when
      var artists = stateDefinition.resolve.artistsPicsRotate();

      // then
      expect(artists).toBeDefined();
      expect(dataFactory.getArtists).toHaveBeenCalled();
      expect(dataFactory.getArtists.calls.count()).toEqual(1);
    });  
  });
});
S.Klechkovski
  • 4,005
  • 16
  • 27