uxtx
uxtx

Reputation: 329

Testing output from event listener in Angular service

This is a problem that's been stuming me for a few days. Plunkr with code sample is here: http://plnkr.co/edit/QHJCyKfM2yFyCQzB68GS?p=preview

Basically, I have a service factory that is listening for an event and returning a value.

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.$on("myEvent", function(args, value) {
    $scope.myEventCalled = true;
  });
});

app.factory('myService', function($rootScope){
  var mysvc = {}
  mysvc.testVar = true
  $rootScope.$on('otherEvent', function(args, value){
    $rootScope.rootCalled = true;
    mysvc.testVar = false;
  });
  return mysvc

});

My test is:

describe('Testing a Hello World controller', function() {
  var $scope = null;
  var svc = null

  //you need to indicate your module in a test
  beforeEach(module('plunker'));

  it('should be able to see settings in service', inject(function($rootScope, $controller) {
    $scope = $rootScope.$new();

    inject(function($httpBackend, myService) {
      svc = myService
    })

    expect(svc).toBeDefined();
    expect(svc.testVar).toBe(true);
  }));

  it('should invoke otherEvent when  "otherEvent" broadcasted in service', inject(function($rootScope, $controller) {
    $scope = $rootScope.$new();

    inject(function($httpBackend, myService) {
      svc = myService
    })

    $scope.$broadcast('otherEvent');
    expect(svc.testVar).toBe(false);
  }));
});

The first test passes but the second test fails, as it's not able to trigger the event and access the modified value.

I get how to test this with a controller, but verifying that the value has been changed from a service has escaped me. I would be grateful for any suggestions.

Upvotes: 1

Views: 799

Answers (1)

tasseKATT
tasseKATT

Reputation: 38490

myService is listening on $rootScope, but in your second test the event is broadcasted on $scope. Since $broadcast dispatches an event name downwards to all child scopes and their children, it will not reach $rootScope.

Change it to this in the second test and it will work:

$rootScope.$broadcast('otherEvent');

However, when testing a controller it's recommended to use mocked versions of its dependencies and only test the controllers own functionality in isolation. In the same fashion each service should get its own spec.

Upvotes: 1

Related Questions