Jackie
Jackie

Reputation: 23577

Test Angular controller calls service function exactly once using Jasmine

I have the following...

app.controller('testCtrl', function(testService){
   testService.doSomething();
});
app.service('testService', function(){
   this.doSomething = function(){...};
});

I want to use Jasmine to ensure doSomething is called once and only once. I seem to be having some trouble doing this.

Also, I am currently grabbing my controller from a compiled element like this...

var element = angular.element('<my-test-directive />');
controller = view.controller('testCtrl');

So extra appreciation if it fits with this sort of formatting

Update

I tried this...

describe("Testing", function () {
  var $rootScope,
    $scope,
    $compile,
    testService,
    view,
    $controller;
  beforeEach(module("app"));
  function createController() {
    return $controller('testCtrl', {
        $scope: scope,
        testService:testService
    });

  }
  function SetUpScope(_$controller_,  _$compile_, _$rootScope_, _testService_) {
    $compile = _$compile_;
    $rootScope = _$rootScope_;
    $scope = $rootScope.$new();
    $controller = _$controller_;
    testService = _testService_;
    spyOn(testService, 'doSomething');
  }
  SetUpScope.$inject = ["$controller","$compile", "$rootScope", "testService"];
  beforeEach(inject(SetUpScope));
  it("On intitialization, the controller should register itself with the list service", function(done){
    createController();
    scope.$digest();
    expect(workOrderService.doSomething).toHaveBeenCalled();
  })
});

It seems to work

Upvotes: 1

Views: 901

Answers (1)

lanan
lanan

Reputation: 2752

It is probably better to test controller in isolation and use Jasmine spies for this:

spyOn(testService, 'doSomething');
expect(testService.doSomething.calls.count()).toEqual(0);

Something like this should work in the actual test.

describe('testCtrl function', function() {

  describe('testCtrl', function() {
    var $scope, testService;

    beforeEach(module('myApp'));

    beforeEach(inject(function($rootScope, $controller, _testService_) {
      $scope = $rootScope.$new();
      testService = _testService_;
      spyOn(testService, 'doSomething');
      $controller('MyController', {$scope: $scope});
    }));

    it('should call testService.doSomething()', function() {
      expect(testService.doSomething.calls.count()).toEqual(1);
    });
  });
});

Here is a quick plunkr http://plnkr.co/edit/Swso4Y

Depending on which version of Jasmine you are using you might need to use

expect(testService.doSomething.calls.length).toEqual(1);

Upvotes: 2

Related Questions