Question

We have an analytics service which is dependency injected to most of our controllers to help us track actions users make.

Rather than going through setting up the mock version of this service every time a test suite is created it's preferred to take the ngMock approach and abstract the mocking. What's the best approach?

Was it helpful?

Solution

EDIT

Looks like you can just override the service by loading a module which replaces it.

http://plnkr.co/edit/mHI19j6FDtV8UElRWvUs?p=preview


http://plnkr.co/edit/lZg8eQdoQRNtqedcr2UU?p=preview

One thing you could do, if I understand your issue correctly, is to not have your modules with your controller depend on that tracking service, and put that dependency in at the app level. Then, in your tests, just load the module containing the mocked version explicitly.

So like:

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

core.controller('MainCtrl', function($scope, tracker) {
  $scope.track = tracker.track();
});

analytics.factory('tracker', function () {
  var service = {};

  service.track = function () {
    return "I'm real";
  }

  return service;
});

mockAnalytics.factory('tracker', function () {
  var service = {};

  service.track = function () {
    return "I'm a mock";
  }

  return service;
});

Tests:

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

  beforeEach(module('core'));
  beforeEach(module('mockAnalytics'));

  beforeEach(inject(function($rootScope, $controller) {
    $scope = $rootScope.$new();

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

  it('should have its $scope.track == "I\'m a mock"', function() {
    expect($scope.track).toEqual("I'm a mock");
  });
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top